summaryrefslogtreecommitdiffstats
path: root/accessibility/source/standard
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /accessibility/source/standard
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--accessibility/source/standard/accessiblemenubasecomponent.cxx716
-rw-r--r--accessibility/source/standard/accessiblemenucomponent.cxx423
-rw-r--r--accessibility/source/standard/accessiblemenuitemcomponent.cxx472
-rw-r--r--accessibility/source/standard/floatingwindowaccessible.cxx45
-rw-r--r--accessibility/source/standard/svtaccessiblenumericfield.cxx105
-rw-r--r--accessibility/source/standard/vclxaccessiblebox.cxx525
-rw-r--r--accessibility/source/standard/vclxaccessiblebutton.cxx310
-rw-r--r--accessibility/source/standard/vclxaccessiblecheckbox.cxx342
-rw-r--r--accessibility/source/standard/vclxaccessiblecombobox.cxx54
-rw-r--r--accessibility/source/standard/vclxaccessibledropdowncombobox.cxx73
-rw-r--r--accessibility/source/standard/vclxaccessibledropdownlistbox.cxx51
-rw-r--r--accessibility/source/standard/vclxaccessibleedit.cxx608
-rw-r--r--accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx38
-rw-r--r--accessibility/source/standard/vclxaccessiblefixedtext.cxx54
-rw-r--r--accessibility/source/standard/vclxaccessibleheaderbar.cxx130
-rw-r--r--accessibility/source/standard/vclxaccessibleheaderbaritem.cxx265
-rw-r--r--accessibility/source/standard/vclxaccessiblelist.cxx942
-rw-r--r--accessibility/source/standard/vclxaccessiblelistbox.cxx53
-rw-r--r--accessibility/source/standard/vclxaccessiblelistitem.cxx617
-rw-r--r--accessibility/source/standard/vclxaccessiblemenu.cxx233
-rw-r--r--accessibility/source/standard/vclxaccessiblemenubar.cxx187
-rw-r--r--accessibility/source/standard/vclxaccessiblemenuitem.cxx579
-rw-r--r--accessibility/source/standard/vclxaccessiblemenuseparator.cxx50
-rw-r--r--accessibility/source/standard/vclxaccessiblepopupmenu.cxx84
-rw-r--r--accessibility/source/standard/vclxaccessibleradiobutton.cxx281
-rw-r--r--accessibility/source/standard/vclxaccessiblescrollbar.cxx272
-rw-r--r--accessibility/source/standard/vclxaccessiblestatusbar.cxx335
-rw-r--r--accessibility/source/standard/vclxaccessiblestatusbaritem.cxx587
-rw-r--r--accessibility/source/standard/vclxaccessibletabcontrol.cxx488
-rw-r--r--accessibility/source/standard/vclxaccessibletabpage.cxx675
-rw-r--r--accessibility/source/standard/vclxaccessibletabpagewindow.cxx133
-rw-r--r--accessibility/source/standard/vclxaccessibletextcomponent.cxx376
-rw-r--r--accessibility/source/standard/vclxaccessibletextfield.cxx107
-rw-r--r--accessibility/source/standard/vclxaccessibletoolbox.cxx866
-rw-r--r--accessibility/source/standard/vclxaccessibletoolboxitem.cxx734
35 files changed, 11810 insertions, 0 deletions
diff --git a/accessibility/source/standard/accessiblemenubasecomponent.cxx b/accessibility/source/standard/accessiblemenubasecomponent.cxx
new file mode 100644
index 000000000..f28bf8ad0
--- /dev/null
+++ b/accessibility/source/standard/accessiblemenubasecomponent.cxx
@@ -0,0 +1,716 @@
+/* -*- 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 <standard/accessiblemenubasecomponent.hxx>
+#include <standard/vclxaccessiblemenu.hxx>
+#include <standard/vclxaccessiblemenuitem.hxx>
+#include <standard/vclxaccessiblemenuseparator.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/vclevent.hxx>
+
+#include <array>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// OAccessibleMenuBaseComponent
+
+
+OAccessibleMenuBaseComponent::OAccessibleMenuBaseComponent( Menu* pMenu )
+ :m_pMenu( pMenu )
+ ,m_bEnabled( false )
+ ,m_bFocused( false )
+ ,m_bVisible( false )
+ ,m_bSelected( false )
+ ,m_bChecked( false )
+{
+ if ( m_pMenu )
+ {
+ m_aAccessibleChildren.assign( m_pMenu->GetItemCount(), Reference< XAccessible >() );
+ m_pMenu->AddEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+ }
+}
+
+
+OAccessibleMenuBaseComponent::~OAccessibleMenuBaseComponent()
+{
+ if ( m_pMenu )
+ m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+}
+
+
+bool OAccessibleMenuBaseComponent::IsEnabled()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsFocused()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsVisible()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsSelected()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsChecked()
+{
+ return false;
+}
+
+
+void OAccessibleMenuBaseComponent::SetStates()
+{
+ m_bEnabled = IsEnabled();
+ m_bFocused = IsFocused();
+ m_bVisible = IsVisible();
+ m_bSelected = IsSelected();
+ m_bChecked = IsChecked();
+}
+
+
+void OAccessibleMenuBaseComponent::SetEnabled( bool bEnabled )
+{
+ if ( m_bEnabled == bEnabled )
+ return;
+
+ sal_Int16 nStateType=AccessibleStateType::ENABLED;
+ if (IsMenuHideDisabledEntries())
+ {
+ nStateType = AccessibleStateType::VISIBLE;
+ }
+ std::array<Any, 2> aOldValue, aNewValue;
+ if ( m_bEnabled )
+ {
+ aOldValue[0] <<= AccessibleStateType::SENSITIVE;
+ aOldValue[1] <<= nStateType;
+ }
+ else
+ {
+ aNewValue[0] <<= nStateType;
+ aNewValue[1] <<= AccessibleStateType::SENSITIVE;
+ }
+ m_bEnabled = bEnabled;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
+}
+
+
+void OAccessibleMenuBaseComponent::SetFocused( bool bFocused )
+{
+ if ( m_bFocused != bFocused )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bFocused )
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ else
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ m_bFocused = bFocused;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::SetVisible( bool bVisible )
+{
+ if ( m_bVisible != bVisible )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bVisible )
+ aOldValue <<= AccessibleStateType::VISIBLE;
+ else
+ aNewValue <<= AccessibleStateType::VISIBLE;
+ m_bVisible = bVisible;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::SetSelected( bool bSelected )
+{
+ if ( m_bSelected != bSelected )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::SetChecked( bool bChecked )
+{
+ if ( m_bChecked != bChecked )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bChecked )
+ aOldValue <<= AccessibleStateType::CHECKED;
+ else
+ aNewValue <<= AccessibleStateType::CHECKED;
+ m_bChecked = bChecked;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateEnabled( sal_Int32 i, bool bEnabled )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetEnabled( bEnabled );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateFocused( sal_Int32 i, bool bFocused )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetFocused( bFocused );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateVisible()
+{
+ SetVisible( IsVisible() );
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetVisible( pComp->IsVisible() );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateSelected( sal_Int32 i, bool bSelected )
+{
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetSelected( bSelected );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateChecked( sal_Int32 i, bool bChecked )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetChecked( bChecked );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateAccessibleName( sal_Int32 i )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetAccessibleName( pComp->GetAccessibleName() );
+ }
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::UpdateItemText( sal_Int32 i )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
+ if ( pComp )
+ pComp->SetItemText( pComp->GetItemText() );
+ }
+ }
+}
+
+
+sal_Int32 OAccessibleMenuBaseComponent::GetChildCount() const
+{
+ return m_aAccessibleChildren.size();
+}
+
+
+Reference< XAccessible > OAccessibleMenuBaseComponent::GetChild( sal_Int32 i )
+{
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ if ( m_pMenu )
+ {
+ // create a new child
+ rtl::Reference<OAccessibleMenuBaseComponent> pChild;
+
+ if ( m_pMenu->GetItemType( static_cast<sal_uInt16>(i) ) == MenuItemType::SEPARATOR )
+ {
+ pChild = new VCLXAccessibleMenuSeparator( m_pMenu, static_cast<sal_uInt16>(i) );
+ }
+ else
+ {
+ PopupMenu* pPopupMenu = m_pMenu->GetPopupMenu( m_pMenu->GetItemId( static_cast<sal_uInt16>(i) ) );
+ if ( pPopupMenu )
+ {
+ pChild = new VCLXAccessibleMenu( m_pMenu, static_cast<sal_uInt16>(i), pPopupMenu );
+ pPopupMenu->SetAccessible( pChild );
+ }
+ else
+ {
+ pChild = new VCLXAccessibleMenuItem( m_pMenu, static_cast<sal_uInt16>(i) );
+ }
+ }
+
+ // set states
+ pChild->SetStates();
+
+ xChild = pChild;
+
+ // insert into menu item list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+}
+
+
+Reference< XAccessible > OAccessibleMenuBaseComponent::GetChildAt( const awt::Point& rPoint )
+{
+ Reference< XAccessible > xChild;
+ for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+}
+
+
+void OAccessibleMenuBaseComponent::InsertChild( sal_Int32 i )
+{
+ if ( i < 0 )
+ return;
+
+ if ( o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ i = m_aAccessibleChildren.size();
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // update item position of accessible children
+ for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
+ {
+ Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
+ if ( xAcc.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
+ if ( pComp )
+ pComp->SetItemPos( static_cast<sal_uInt16>(j) );
+ }
+ }
+
+ // send accessible child event
+ Reference< XAccessible > xChild( GetChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void OAccessibleMenuBaseComponent::RemoveChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // keep the accessible of the removed item
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // update item position of accessible children
+ for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
+ {
+ Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
+ if ( xAcc.is() )
+ {
+ OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
+ if ( pComp )
+ pComp->SetItemPos( static_cast<sal_uInt16>(j) );
+ }
+ }
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+}
+
+
+bool OAccessibleMenuBaseComponent::IsHighlighted()
+{
+ return false;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsChildHighlighted()
+{
+ bool bChildHighlighted = false;
+
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
+ if ( pComp && pComp->IsHighlighted() )
+ {
+ bChildHighlighted = true;
+ break;
+ }
+ }
+ }
+
+ return bChildHighlighted;
+}
+
+
+void OAccessibleMenuBaseComponent::SelectChild( sal_Int32 i )
+{
+ // open the menu
+ if ( getAccessibleRole() == AccessibleRole::MENU && !IsPopupMenuOpen() )
+ Click();
+
+ // highlight the child
+ if ( m_pMenu )
+ m_pMenu->HighlightItem( static_cast<sal_uInt16>(i) );
+}
+
+
+void OAccessibleMenuBaseComponent::DeSelectAll()
+{
+ if ( m_pMenu )
+ m_pMenu->DeHighlight();
+}
+
+
+bool OAccessibleMenuBaseComponent::IsChildSelected( sal_Int32 i )
+{
+ bool bSelected = false;
+
+ if ( m_pMenu && m_pMenu->IsHighlighted( static_cast<sal_uInt16>(i) ) )
+ bSelected = true;
+
+ return bSelected;
+}
+
+
+void OAccessibleMenuBaseComponent::Click()
+{
+}
+
+
+bool OAccessibleMenuBaseComponent::IsPopupMenuOpen()
+{
+ return false;
+}
+
+
+IMPL_LINK( OAccessibleMenuBaseComponent, MenuEventListener, VclMenuEvent&, rEvent, void )
+{
+ OSL_ENSURE( rEvent.GetMenu(), "OAccessibleMenuBaseComponent - Menu?" );
+ ProcessMenuEvent( rEvent );
+}
+
+
+void OAccessibleMenuBaseComponent::ProcessMenuEvent( const VclMenuEvent& rVclMenuEvent )
+{
+ sal_uInt16 nItemPos = rVclMenuEvent.GetItemPos();
+
+ switch ( rVclMenuEvent.GetId() )
+ {
+ case VclEventId::MenuShow:
+ case VclEventId::MenuHide:
+ {
+ UpdateVisible();
+ }
+ break;
+ case VclEventId::MenuHighlight:
+ {
+ SetFocused( false );
+ UpdateFocused( nItemPos, true );
+ UpdateSelected( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuDehighlight:
+ {
+ UpdateFocused( nItemPos, false );
+ UpdateSelected( nItemPos, false );
+ }
+ break;
+ case VclEventId::MenuSubmenuActivate:
+ {
+ }
+ break;
+ case VclEventId::MenuSubmenuDeactivate:
+ {
+ UpdateFocused( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuEnable:
+ {
+ UpdateEnabled( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuDisable:
+ {
+ UpdateEnabled( nItemPos, false );
+ }
+ break;
+ case VclEventId::MenuSubmenuChanged:
+ {
+ RemoveChild( nItemPos );
+ InsertChild( nItemPos );
+ }
+ break;
+ case VclEventId::MenuInsertItem:
+ {
+ InsertChild( nItemPos );
+ }
+ break;
+ case VclEventId::MenuRemoveItem:
+ {
+ RemoveChild( nItemPos );
+ }
+ break;
+ case VclEventId::MenuAccessibleNameChanged:
+ {
+ UpdateAccessibleName( nItemPos );
+ }
+ break;
+ case VclEventId::MenuItemTextChanged:
+ {
+ UpdateAccessibleName( nItemPos );
+ UpdateItemText( nItemPos );
+ }
+ break;
+ case VclEventId::MenuItemChecked:
+ {
+ UpdateChecked( nItemPos, true );
+ }
+ break;
+ case VclEventId::MenuItemUnchecked:
+ {
+ UpdateChecked( nItemPos, false );
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pMenu )
+ {
+ m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+
+ m_pMenu = nullptr;
+
+ // dispose all menu items
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuBaseComponent, OAccessibleExtendedComponentHelper, OAccessibleMenuBaseComponent_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuBaseComponent, OAccessibleExtendedComponentHelper, OAccessibleMenuBaseComponent_BASE )
+
+
+// XComponent
+
+
+void OAccessibleMenuBaseComponent::disposing()
+{
+ OAccessibleExtendedComponentHelper::disposing();
+
+ if ( !m_pMenu )
+ return;
+
+ m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
+
+ m_pMenu = nullptr;
+
+ // dispose all menu items
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+}
+
+
+// XServiceInfo
+
+
+sal_Bool OAccessibleMenuBaseComponent::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+
+// XAccessible
+
+
+Reference< XAccessibleContext > OAccessibleMenuBaseComponent::getAccessibleContext( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+Reference< XAccessibleStateSet > OAccessibleMenuBaseComponent::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+bool OAccessibleMenuBaseComponent::IsMenuHideDisabledEntries()
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/accessiblemenucomponent.cxx b/accessibility/source/standard/accessiblemenucomponent.cxx
new file mode 100644
index 000000000..be9b1e6f4
--- /dev/null
+++ b/accessibility/source/standard/accessiblemenucomponent.cxx
@@ -0,0 +1,423 @@
+/* -*- 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 <standard/accessiblemenucomponent.hxx>
+
+#include <toolkit/awt/vclxfont.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+bool OAccessibleMenuComponent::IsEnabled()
+{
+ return true;
+}
+
+
+bool OAccessibleMenuComponent::IsVisible()
+{
+ bool bVisible = false;
+
+ if ( m_pMenu )
+ bVisible = m_pMenu->IsMenuVisible();
+
+ return bVisible;
+}
+
+
+void OAccessibleMenuComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ if ( IsEnabled() )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsFocused() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ if ( IsVisible() )
+ {
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+ }
+
+ rStateSet.AddState( AccessibleStateType::OPAQUE );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle OAccessibleMenuComponent::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ // get bounding rectangle of the window in screen coordinates
+ tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
+ aBounds = AWTRectangle( aRect );
+
+ // get position of the accessible parent in screen coordinates
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComponent.is() )
+ {
+ awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
+
+ // calculate position of the window relative to the accessible parent
+ aBounds.X -= aParentScreenLoc.X;
+ aBounds.Y -= aParentScreenLoc.Y;
+ }
+ }
+ }
+ }
+
+ return aBounds;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
+
+
+// XAccessibleContext
+
+
+sal_Int32 OAccessibleMenuComponent::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildCount();
+}
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return GetChild( i );
+}
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
+ if ( pParent )
+ xParent = pParent->GetAccessible();
+ }
+ }
+
+ return xParent;
+}
+
+
+sal_Int16 OAccessibleMenuComponent::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::UNKNOWN;
+}
+
+
+OUString OAccessibleMenuComponent::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ sDescription = pWindow->GetAccessibleDescription();
+ }
+
+ return sDescription;
+}
+
+
+OUString OAccessibleMenuComponent::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+Reference< XAccessibleRelationSet > OAccessibleMenuComponent::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Locale OAccessibleMenuComponent::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildAt( rPoint );
+}
+
+
+awt::Point OAccessibleMenuComponent::getLocationOnScreen( )
+{
+ OExternalLockGuard aGuard( this );
+
+ awt::Point aPos;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
+ aPos = AWTPoint( aRect.TopLeft() );
+ }
+ }
+
+ return aPos;
+}
+
+
+void OAccessibleMenuComponent::grabFocus( )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ pWindow->GrabFocus();
+ }
+}
+
+
+sal_Int32 OAccessibleMenuComponent::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ Color nColor = rStyleSettings.GetMenuTextColor();
+
+ return sal_Int32(nColor);
+}
+
+
+sal_Int32 OAccessibleMenuComponent::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > OAccessibleMenuComponent::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), UNO_QUERY );
+ if ( xDev.is() )
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont;
+ pVCLXFont->Init( *xDev, rStyleSettings.GetMenuFont() );
+ xFont = pVCLXFont;
+ }
+ }
+ }
+
+ return xFont;
+}
+
+
+OUString OAccessibleMenuComponent::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+OUString OAccessibleMenuComponent::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleSelection
+
+
+void OAccessibleMenuComponent::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ SelectChild( nChildIndex );
+}
+
+
+sal_Bool OAccessibleMenuComponent::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return IsChildSelected( nChildIndex );
+}
+
+
+void OAccessibleMenuComponent::clearAccessibleSelection( )
+{
+ OExternalLockGuard aGuard( this );
+
+ DeSelectAll();
+}
+
+
+void OAccessibleMenuComponent::selectAllAccessibleChildren( )
+{
+ // This method makes no sense in a menu, and so does nothing.
+}
+
+
+sal_Int32 OAccessibleMenuComponent::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nRet = 0;
+
+ for ( sal_Int32 i = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+
+Reference< XAccessible > OAccessibleMenuComponent::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( sal_Int32 i = 0, j = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
+ {
+ xChild = GetChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+}
+
+
+void OAccessibleMenuComponent::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ DeSelectAll();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/accessiblemenuitemcomponent.cxx b/accessibility/source/standard/accessiblemenuitemcomponent.cxx
new file mode 100644
index 000000000..e61c7452e
--- /dev/null
+++ b/accessibility/source/standard/accessiblemenuitemcomponent.cxx
@@ -0,0 +1,472 @@
+/* -*- 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 <standard/accessiblemenuitemcomponent.hxx>
+
+
+#include <toolkit/helper/convert.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <comphelper/accessibletexthelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+OAccessibleMenuItemComponent::OAccessibleMenuItemComponent( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu )
+ :OAccessibleMenuBaseComponent( pMenu )
+ ,m_pParent( pParent )
+ ,m_nItemPos( nItemPos )
+{
+ m_sAccessibleName = GetAccessibleName();
+ m_sItemText = GetItemText();
+}
+
+OAccessibleMenuItemComponent::~OAccessibleMenuItemComponent()
+{
+}
+
+bool OAccessibleMenuItemComponent::IsEnabled()
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bEnabled = false;
+ if ( m_pParent )
+ bEnabled = m_pParent->IsItemEnabled( m_pParent->GetItemId( m_nItemPos ) );
+
+ return bEnabled;
+}
+
+
+bool OAccessibleMenuItemComponent::IsVisible()
+{
+ bool bVisible = false;
+
+ if ( m_pParent )
+ bVisible = m_pParent->IsItemPosVisible( m_nItemPos );
+
+ return bVisible;
+}
+
+
+void OAccessibleMenuItemComponent::Select()
+{
+ // open the parent menu
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if ( xParent.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xParent.get() );
+ if ( pComp && pComp->getAccessibleRole() == AccessibleRole::MENU && !pComp->IsPopupMenuOpen() )
+ pComp->Click();
+ }
+
+ // highlight the menu item
+ if ( m_pParent )
+ m_pParent->HighlightItem( m_nItemPos );
+}
+
+
+void OAccessibleMenuItemComponent::DeSelect()
+{
+ if ( m_pParent && IsSelected() )
+ m_pParent->DeHighlight();
+}
+
+
+void OAccessibleMenuItemComponent::Click()
+{
+ // open the parent menu
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if ( xParent.is() )
+ {
+ OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xParent.get() );
+ if ( pComp && pComp->getAccessibleRole() == AccessibleRole::MENU && !pComp->IsPopupMenuOpen() )
+ pComp->Click();
+ }
+
+ // click the menu item
+ if ( !m_pParent )
+ return;
+
+ vcl::Window* pWindow = m_pParent->GetWindow();
+ if ( !pWindow )
+ return;
+
+ // #102438# Menu items are not selectable
+ // Popup menus are executed asynchronously, triggered by a timer.
+ // As Menu::SelectItem only works, if the corresponding menu window is
+ // already created, we have to set the menu delay to 0, so
+ // that the popup menus are executed synchronously.
+ AllSettings aSettings = pWindow->GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
+ sal_Int32 nDelay = aMouseSettings.GetMenuDelay();
+ aMouseSettings.SetMenuDelay( 0 );
+ aSettings.SetMouseSettings( aMouseSettings );
+ pWindow->SetSettings( aSettings );
+
+ m_pParent->SelectItem( m_pParent->GetItemId( m_nItemPos ) );
+
+ // meanwhile the window pointer may be invalid
+ pWindow = m_pParent->GetWindow();
+ if ( pWindow )
+ {
+ // set the menu delay back to the old value
+ aSettings = pWindow->GetSettings();
+ aMouseSettings = aSettings.GetMouseSettings();
+ aMouseSettings.SetMenuDelay( nDelay );
+ aSettings.SetMouseSettings( aMouseSettings );
+ pWindow->SetSettings( aSettings );
+ }
+}
+
+
+void OAccessibleMenuItemComponent::SetItemPos( sal_uInt16 nItemPos )
+{
+ m_nItemPos = nItemPos;
+}
+
+
+void OAccessibleMenuItemComponent::SetAccessibleName( const OUString& sAccessibleName )
+{
+ if ( m_sAccessibleName != sAccessibleName )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sAccessibleName;
+ aNewValue <<= sAccessibleName;
+ m_sAccessibleName = sAccessibleName;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString OAccessibleMenuItemComponent::GetAccessibleName()
+{
+ OUString sName;
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ sName = m_pParent->GetAccessibleName( nItemId );
+ if ( sName.isEmpty() )
+ sName = m_pParent->GetItemText( nItemId );
+ sName = OutputDevice::GetNonMnemonicString( sName );
+#if defined(_WIN32)
+ if ( m_pParent->GetAccelKey( nItemId ).GetName().getLength() )
+ sName += "\t" + m_pParent->GetAccelKey(nItemId).GetName();
+#endif
+ }
+
+ return sName;
+}
+
+
+void OAccessibleMenuItemComponent::SetItemText( const OUString& sItemText )
+{
+ Any aOldValue, aNewValue;
+ if ( OCommonAccessibleText::implInitTextChangedEvent( m_sItemText, sItemText, aOldValue, aNewValue ) )
+ {
+ m_sItemText = sItemText;
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString OAccessibleMenuItemComponent::GetItemText()
+{
+ OUString sText;
+ if ( m_pParent )
+ sText = OutputDevice::GetNonMnemonicString( m_pParent->GetItemText( m_pParent->GetItemId( m_nItemPos ) ) );
+
+ return sText;
+}
+
+
+void OAccessibleMenuItemComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ bool bEnabled = IsEnabled();
+ if ( bEnabled )
+ {
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ if ( IsVisible() )
+ {
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+ if( !IsMenuHideDisabledEntries() || bEnabled )
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ }
+ rStateSet.AddState( AccessibleStateType::OPAQUE );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle OAccessibleMenuItemComponent::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pParent )
+ {
+ // get bounding rectangle of the item relative to the containing window
+ aBounds = AWTRectangle( m_pParent->GetBoundingRectangle( m_nItemPos ) );
+
+ // get position of containing window in screen coordinates
+ vcl::Window* pWindow = m_pParent->GetWindow();
+ if ( pWindow )
+ {
+ tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
+ awt::Point aWindowScreenLoc = AWTPoint( aRect.TopLeft() );
+
+ // get position of accessible parent in screen coordinates
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComponent.is() )
+ {
+ awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
+
+ // calculate bounding rectangle of the item relative to the accessible parent
+ aBounds.X += aWindowScreenLoc.X - aParentScreenLoc.X;
+ aBounds.Y += aWindowScreenLoc.Y - aParentScreenLoc.Y;
+ }
+ }
+ }
+ }
+
+ return aBounds;
+}
+
+
+// XComponent
+
+
+void SAL_CALL OAccessibleMenuItemComponent::disposing()
+{
+ OAccessibleMenuBaseComponent::disposing();
+
+ m_pParent = nullptr;
+ m_sAccessibleName.clear();
+ m_sItemText.clear();
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 OAccessibleMenuItemComponent::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessible >();
+}
+
+
+Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_pParent->GetAccessible();
+}
+
+
+sal_Int32 OAccessibleMenuItemComponent::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_nItemPos;
+}
+
+
+sal_Int16 OAccessibleMenuItemComponent::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::UNKNOWN;
+}
+
+
+OUString OAccessibleMenuItemComponent::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pParent )
+ sDescription = m_pParent->GetAccessibleDescription( m_pParent->GetItemId( m_nItemPos ) );
+
+ return sDescription;
+}
+
+
+OUString OAccessibleMenuItemComponent::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_sAccessibleName;
+}
+
+
+Reference< XAccessibleRelationSet > OAccessibleMenuItemComponent::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Locale OAccessibleMenuItemComponent::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleAtPoint( const awt::Point& )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Reference< XAccessible >();
+}
+
+
+void OAccessibleMenuItemComponent::grabFocus( )
+{
+ // no focus for items
+}
+
+
+sal_Int32 OAccessibleMenuItemComponent::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+}
+
+
+sal_Int32 OAccessibleMenuItemComponent::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > OAccessibleMenuItemComponent::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+}
+
+
+OUString OAccessibleMenuItemComponent::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+OUString OAccessibleMenuItemComponent::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( m_pParent )
+ sRet = m_pParent->GetTipHelpText( m_pParent->GetItemId( m_nItemPos ) );
+
+ return sRet;
+}
+
+
+bool OAccessibleMenuItemComponent::IsMenuHideDisabledEntries()
+{
+ if (m_pParent )
+ {
+ if( m_pParent->GetMenuFlags() & MenuFlags::HideDisabledEntries)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/floatingwindowaccessible.cxx b/accessibility/source/standard/floatingwindowaccessible.cxx
new file mode 100644
index 000000000..aa5ef41f6
--- /dev/null
+++ b/accessibility/source/standard/floatingwindowaccessible.cxx
@@ -0,0 +1,45 @@
+/* -*- 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 <floatingwindowaccessible.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/window.hxx>
+
+namespace uno = ::com::sun::star::uno;
+
+using ::com::sun::star::accessibility::AccessibleRelation;
+namespace AccessibleRelationType = ::com::sun::star::accessibility::AccessibleRelationType;
+
+void FloatingWindowAccessible::FillAccessibleRelationSet(utl::AccessibleRelationSetHelper& rRelationSet)
+{
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ vcl::Window* pParentWindow = pWindow->GetParent();
+ if( pParentWindow )
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pParentWindow->GetAccessible() };
+ rRelationSet.AddRelation( AccessibleRelation( AccessibleRelationType::SUB_WINDOW_OF, aSequence ) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/svtaccessiblenumericfield.cxx b/accessibility/source/standard/svtaccessiblenumericfield.cxx
new file mode 100644
index 000000000..729966eb8
--- /dev/null
+++ b/accessibility/source/standard/svtaccessiblenumericfield.cxx
@@ -0,0 +1,105 @@
+/* -*- 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 <standard/svtaccessiblenumericfield.hxx>
+#include <toolkit/awt/vclxwindows.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+SVTXAccessibleNumericField::SVTXAccessibleNumericField(VCLXWindow* pVCLWindow)
+ : VCLXAccessibleEdit(pVCLWindow)
+{
+}
+
+// XInterface
+IMPLEMENT_FORWARD_XINTERFACE2(SVTXAccessibleNumericField, VCLXAccessibleTextComponent,
+ SVTXAccessibleNumericField_BASE)
+
+// XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(SVTXAccessibleNumericField, VCLXAccessibleTextComponent,
+ SVTXAccessibleNumericField_BASE)
+
+sal_Int16 SVTXAccessibleNumericField::getAccessibleRole() { return AccessibleRole::SPIN_BOX; }
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getCurrentValue()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getValue();
+
+ return css::uno::Any(dValue);
+}
+
+sal_Bool SVTXAccessibleNumericField::setCurrentValue(const css::uno::Any& aNumber)
+{
+ OExternalLockGuard aGuard(this);
+
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (!pField)
+ return false;
+
+ double dValue = 0;
+ aNumber >>= dValue;
+ pField->setValue(dValue);
+ return true;
+}
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getMaximumValue()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getMax();
+
+ return css::uno::Any(dValue);
+}
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getMinimumValue()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getMin();
+
+ return css::uno::Any(dValue);
+}
+
+css::uno::Any SAL_CALL SVTXAccessibleNumericField::getMinimumIncrement()
+{
+ OExternalLockGuard aGuard(this);
+
+ double dValue = 0;
+ SVTXNumericField* pField = static_cast<SVTXNumericField*>(GetVCLXWindow());
+ if (pField)
+ dValue = pField->getSpinSize();
+
+ return css::uno::Any(dValue);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblebox.cxx b/accessibility/source/standard/vclxaccessiblebox.cxx
new file mode 100644
index 000000000..ce81c254c
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblebox.cxx
@@ -0,0 +1,525 @@
+/* -*- 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 <standard/vclxaccessiblebox.hxx>
+#include <standard/vclxaccessibletextfield.hxx>
+#include <standard/vclxaccessibleedit.hxx>
+#include <standard/vclxaccessiblelist.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+
+VCLXAccessibleBox::VCLXAccessibleBox (VCLXWindow* pVCLWindow, BoxType aType, bool bIsDropDownBox)
+ : VCLXAccessibleComponent (pVCLWindow),
+ m_aBoxType (aType),
+ m_bIsDropDownBox (bIsDropDownBox)
+{
+ // Set up the flags that indicate which children this object has.
+ m_bHasListChild = true;
+
+ // A text field is not present for non drop down list boxes.
+ if ((m_aBoxType==LISTBOX) && ! m_bIsDropDownBox)
+ m_bHasTextChild = false;
+ else
+ m_bHasTextChild = true;
+}
+
+void VCLXAccessibleBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ uno::Any aOldValue, aNewValue;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow:
+ case VclEventId::WindowHide:
+ {
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ // Just compare to the combo box text field. All other children
+ // are identical to this object in which case this object will
+ // be removed in a short time.
+ if (m_aBoxType==COMBOBOX)
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( ( pComboBox != nullptr ) && ( pChildWindow != nullptr ) )
+ if (pChildWindow == pComboBox->GetSubEdit())
+ {
+ if (rVclWindowEvent.GetId() == VclEventId::WindowShow)
+ {
+ // Instantiate text field.
+ getAccessibleChild (0);
+ aNewValue <<= m_xText;
+ }
+ else
+ {
+ // Release text field.
+ aOldValue <<= m_xText;
+ m_xText = nullptr;
+ }
+ // Tell the listeners about the new/removed child.
+ NotifyAccessibleEvent (
+ AccessibleEventId::CHILD,
+ aOldValue, aNewValue);
+ }
+
+ }
+ }
+ break;
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
+ }
+}
+
+void VCLXAccessibleBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownSelect:
+ case VclEventId::ListboxSelect:
+ {
+ // Forward the call to the list child.
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ {
+ pList->ProcessWindowEvent (rVclWindowEvent, m_bIsDropDownBox);
+#if defined(_WIN32)
+ if (m_bIsDropDownBox)
+ {
+ NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
+ }
+#endif
+ }
+ break;
+ }
+ case VclEventId::DropdownOpen:
+ {
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ {
+ pList->ProcessWindowEvent (rVclWindowEvent);
+ pList->HandleDropOpen();
+ }
+ break;
+ }
+ case VclEventId::DropdownClose:
+ {
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ {
+ pList->ProcessWindowEvent (rVclWindowEvent);
+ }
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow && (pWindow->HasFocus() || pWindow->HasChildPathFocus()) )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ }
+ case VclEventId::ComboboxSelect:
+ {
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if (pList != nullptr && m_xText.is())
+ {
+ Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
+ if ( xText.is() )
+ {
+ OUString sText = xText->getSelectedText();
+ if ( sText.isEmpty() )
+ sText = xText->getText();
+ pList->UpdateSelection_Acc(sText, m_bIsDropDownBox);
+#if defined(_WIN32)
+ if (m_bIsDropDownBox || m_aBoxType==COMBOBOX)
+ NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
+#endif
+ }
+ }
+ break;
+ }
+ //case VclEventId::DropdownOpen:
+ //case VclEventId::DropdownClose:
+ case VclEventId::ListboxDoubleClick:
+ case VclEventId::ListboxScrolled:
+ //case VclEventId::ListboxSelect:
+ case VclEventId::ListboxItemAdded:
+ case VclEventId::ListboxItemRemoved:
+ case VclEventId::ComboboxItemAdded:
+ case VclEventId::ComboboxItemRemoved:
+ {
+ // Forward the call to the list child.
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if ( pList == nullptr )
+ {
+ getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
+ pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ }
+ if ( pList != nullptr )
+ pList->ProcessWindowEvent (rVclWindowEvent);
+ break;
+ }
+
+ //case VclEventId::ComboboxSelect:
+ case VclEventId::ComboboxDeselect:
+ {
+ // Selection is handled by VCLXAccessibleList which operates on
+ // the same VCL object as this box does. In case of the
+ // combobox, however, we have to help by providing the list with
+ // the text of the currently selected item.
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if (pList != nullptr && m_xText.is())
+ {
+ Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
+ if ( xText.is() )
+ {
+ OUString sText = xText->getSelectedText();
+ if ( sText.isEmpty() )
+ sText = xText->getText();
+ pList->UpdateSelection (sText);
+ }
+ }
+ break;
+ }
+
+ case VclEventId::EditModify:
+ case VclEventId::EditSelectionChanged:
+ case VclEventId::EditCaretChanged:
+ // Modify/Selection events are handled by the combo box instead of
+ // directly by the edit field (Why?). Therefore, delegate this
+ // call to the edit field.
+ if (m_aBoxType==COMBOBOX)
+ {
+ if (m_xText.is())
+ {
+ Reference<XAccessibleContext> xContext = m_xText->getAccessibleContext();
+ VCLXAccessibleEdit* pEdit = static_cast<VCLXAccessibleEdit*>(xContext.get());
+ if (pEdit != nullptr)
+ pEdit->ProcessWindowEvent (rVclWindowEvent);
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
+
+//===== XAccessible =========================================================
+
+Reference< XAccessibleContext > SAL_CALL VCLXAccessibleBox::getAccessibleContext( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return this;
+}
+
+//===== XAccessibleContext ==================================================
+
+sal_Int32 VCLXAccessibleBox::getAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return implGetAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleBox::implGetAccessibleChildCount()
+{
+ // Usually a box has a text field and a list of items as its children.
+ // Non drop down list boxes have no text field. Additionally check
+ // whether the object is valid.
+ sal_Int32 nCount = 0;
+ if (IsValid())
+ nCount += (m_bHasTextChild?1:0) + (m_bHasListChild?1:0);
+ else
+ {
+ // Object not valid anymore. Release references to children.
+ m_bHasTextChild = false;
+ m_xText = nullptr;
+ m_bHasListChild = false;
+ m_xList = nullptr;
+ }
+
+ return nCount;
+}
+
+Reference<XAccessible> SAL_CALL VCLXAccessibleBox::getAccessibleChild (sal_Int32 i)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if (i<0 || i>=implGetAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ if (IsValid())
+ {
+ if (i==1 || ! m_bHasTextChild)
+ {
+ // List.
+ if ( ! m_xList.is())
+ {
+ rtl::Reference<VCLXAccessibleList> pList = new VCLXAccessibleList ( GetVCLXWindow(),
+ (m_aBoxType == LISTBOX ? VCLXAccessibleList::LISTBOX : VCLXAccessibleList::COMBOBOX),
+ this);
+ pList->SetIndexInParent (i);
+ m_xList = pList;
+ }
+ xChild = m_xList;
+ }
+ else
+ {
+ // Text Field.
+ if ( ! m_xText.is())
+ {
+ if (m_aBoxType==COMBOBOX)
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if (pComboBox!=nullptr && pComboBox->GetSubEdit()!=nullptr)
+ //Set the edit's acc name the same as parent
+ {
+ pComboBox->GetSubEdit()->SetAccessibleName(getAccessibleName());
+ m_xText = pComboBox->GetSubEdit()->GetAccessible();
+ }
+ }
+ else if (m_bIsDropDownBox)
+ m_xText = new VCLXAccessibleTextField (GetVCLXWindow(),this);
+ }
+ xChild = m_xText;
+ }
+ }
+
+ return xChild;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleBox::getAccessibleRole()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ // Return the role <const>COMBO_BOX</const> for both VCL combo boxes and
+ // VCL list boxes in DropDown-Mode else <const>PANEL</const>.
+ // This way the Java bridge has not to handle both independently.
+ //return m_bIsDropDownBox ? AccessibleRole::COMBO_BOX : AccessibleRole::PANEL;
+ if (m_bIsDropDownBox || (m_aBoxType == COMBOBOX))
+ return AccessibleRole::COMBO_BOX;
+ else
+ return AccessibleRole::PANEL;
+}
+
+//===== XAccessibleAction ===================================================
+
+sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleActionCount()
+{
+ ::osl::Guard< ::osl::Mutex> aGuard (GetMutex());
+
+ // There is one action for drop down boxes (toggle popup) and none for
+ // the other boxes.
+ return m_bIsDropDownBox ? 1 : 0;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleBox::doAccessibleAction (sal_Int32 nIndex)
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if (nIndex!=0 || !m_bIsDropDownBox)
+ throw css::lang::IndexOutOfBoundsException(
+ ("VCLXAccessibleBox::doAccessibleAction: index "
+ + OUString::number(nIndex) + " not among 0.."
+ + OUString::number(getAccessibleActionCount())),
+ static_cast<OWeakObject*>(this));
+
+ if (m_aBoxType == COMBOBOX)
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if (pComboBox != nullptr)
+ {
+ pComboBox->ToggleDropDown();
+ bNotify = true;
+ }
+ }
+ else if (m_aBoxType == LISTBOX)
+ {
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if (pListBox != nullptr)
+ {
+ pListBox->ToggleDropDown();
+ bNotify = true;
+ }
+ }
+ }
+
+ if (bNotify)
+ NotifyAccessibleEvent (AccessibleEventId::ACTION_CHANGED, Any(), Any());
+
+ return bNotify;
+}
+
+OUString SAL_CALL VCLXAccessibleBox::getAccessibleActionDescription (sal_Int32 nIndex)
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ if (nIndex!=0 || !m_bIsDropDownBox)
+ throw css::lang::IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_TOGGLEPOPUP;
+}
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ Reference< XAccessibleKeyBinding > xRet;
+
+ if (nIndex<0 || nIndex>=getAccessibleActionCount())
+ throw css::lang::IndexOutOfBoundsException();
+
+ // ... which key?
+ return xRet;
+}
+
+// ===== XAccessibleValue ===============================================
+Any VCLXAccessibleBox::getCurrentValue( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ Any aAny;
+ if( m_xList.is() && m_xText.is())
+ {
+ // VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
+ if ( xText.is() )
+ {
+ OUString sText = xText->getText();
+ aAny <<= sText;
+ }
+ }
+ if (m_aBoxType == LISTBOX && m_bIsDropDownBox && m_xList.is() )
+ {
+
+ VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
+ if(pList->IsInDropDown())
+ {
+ if(pList->getSelectedAccessibleChildCount()>0)
+ {
+ Reference<XAccessibleContext> xName (pList->getSelectedAccessibleChild(sal_Int32(0)), UNO_QUERY);
+ if(xName.is())
+ {
+ aAny <<= xName->getAccessibleName();
+ }
+ }
+ }
+ }
+
+ return aAny;
+}
+
+sal_Bool VCLXAccessibleBox::setCurrentValue( const Any& aNumber )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ OUString fValue;
+ bool bValid = (aNumber >>= fValue);
+ return bValid;
+
+}
+
+Any VCLXAccessibleBox::getMaximumValue( )
+{
+ Any aAny;
+ return aAny;
+}
+
+Any VCLXAccessibleBox::getMinimumValue( )
+{
+ Any aAny;
+ return aAny;
+}
+
+Any VCLXAccessibleBox::getMinimumIncrement( )
+{
+ return Any();
+}
+
+// Set the INDETERMINATE state when there is no selected item for combobox
+void VCLXAccessibleBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet(rStateSet);
+ if (m_aBoxType == COMBOBOX )
+ {
+ OUString sText;
+ sal_Int32 nEntryCount = 0;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if (pComboBox != nullptr)
+ {
+ Edit* pSubEdit = pComboBox->GetSubEdit();
+ if ( pSubEdit)
+ sText = pSubEdit->GetText();
+ nEntryCount = pComboBox->GetEntryCount();
+ }
+ if ( sText.isEmpty() && nEntryCount > 0 )
+ rStateSet.AddState(AccessibleStateType::INDETERMINATE);
+ }
+ else if (m_aBoxType == LISTBOX && m_bIsDropDownBox)
+ {
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if (pListBox != nullptr && pListBox->GetEntryCount() > 0)
+ {
+ sal_Int32 nSelectedEntryCount = pListBox->GetSelectedEntryCount();
+ if ( nSelectedEntryCount == 0)
+ rStateSet.AddState(AccessibleStateType::INDETERMINATE);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblebutton.cxx b/accessibility/source/standard/vclxaccessiblebutton.cxx
new file mode 100644
index 000000000..d5ffb68bb
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblebutton.cxx
@@ -0,0 +1,310 @@
+/* -*- 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 <standard/vclxaccessiblebutton.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <strings.hxx>
+
+#include <vcl/toolkit/button.hxx>
+#include <vcl/event.hxx>
+#include <vcl/vclevent.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleButton
+
+
+void VCLXAccessibleButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::PushbuttonToggle:
+ {
+ Any aOldValue;
+ Any aNewValue;
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton && pButton->GetState() == TRISTATE_TRUE )
+ aNewValue <<= AccessibleStateType::CHECKED;
+ else
+ aOldValue <<= AccessibleStateType::CHECKED;
+
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleButton::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( !pButton )
+ return;
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( pButton->GetState() == TRISTATE_TRUE )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+
+ if ( pButton->IsPressed() )
+ rStateSet.AddState( AccessibleStateType::PRESSED );
+
+ // IA2 CWS: if the button has a popup menu, it should has the state EXPANDABLE
+ if( pButton->GetType() == WindowType::MENUBUTTON )
+ {
+ rStateSet.AddState( AccessibleStateType::EXPANDABLE );
+ }
+ if( pButton->GetStyle() & WB_DEFBUTTON )
+ {
+ rStateSet.AddState( AccessibleStateType::DEFAULT );
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleButton::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleButton";
+}
+
+
+Sequence< OUString > VCLXAccessibleButton::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleButton" };
+}
+
+
+// XAccessibleContext
+
+
+OUString VCLXAccessibleButton::getAccessibleName( )
+{
+ OUString aName( VCLXAccessibleTextComponent::getAccessibleName() );
+ sal_Int32 nLength = aName.getLength();
+
+ if ( nLength >= 3 && aName.match( "...", nLength - 3 ) )
+ {
+ if ( nLength == 3 )
+ {
+ // it's a browse button
+ aName = AccResId( RID_STR_ACC_NAME_BROWSEBUTTON );
+ }
+ else
+ {
+ // remove the three trailing dots
+ aName = aName.copy( 0, nLength - 3 );
+ }
+ }
+ else if ( nLength >= 3 && aName.match( "<< ", 0 ) )
+ {
+ // remove the leading symbols
+ aName = aName.copy( 3, nLength - 3 );
+ }
+ else if ( nLength >= 3 && aName.match( " >>", nLength - 3 ) )
+ {
+ // remove the trailing symbols
+ aName = aName.copy( 0, nLength - 3 );
+ }
+
+ return aName;
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleButton::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleButton::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ pButton->Click();
+
+ return true;
+}
+
+
+OUString VCLXAccessibleButton::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_CLICK;
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleButton::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ KeyEvent aKeyEvent = pWindow->GetActivationKey();
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ if ( aKeyCode.GetCode() != 0 )
+ {
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ if ( aKeyCode.IsShift() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aKeyCode.IsMod1() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
+ if ( aKeyCode.IsMod2() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
+ if ( aKeyCode.IsMod3() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
+ aKeyStroke.KeyCode = aKeyCode.GetCode();
+ aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
+ aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleButton::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ aValue <<= static_cast<sal_Int32>(pButton->IsPressed());
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleButton::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ {
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue < 0 )
+ nValue = 0;
+ else if ( nValue > 1 )
+ nValue = 1;
+
+ pButton->SetPressed( nValue == 1 );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleButton::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleButton::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleButton::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblecheckbox.cxx b/accessibility/source/standard/vclxaccessiblecheckbox.cxx
new file mode 100644
index 000000000..20cf2138b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblecheckbox.cxx
@@ -0,0 +1,342 @@
+/* -*- 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 <standard/vclxaccessiblecheckbox.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <vcl/toolkit/button.hxx>
+#include <vcl/event.hxx>
+#include <vcl/vclevent.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleCheckBox
+
+
+VCLXAccessibleCheckBox::VCLXAccessibleCheckBox( VCLXWindow* pVCLWindow )
+ :VCLXAccessibleTextComponent( pVCLWindow )
+{
+ m_bChecked = IsChecked();
+ m_bIndeterminate = IsIndeterminate();
+}
+
+
+bool VCLXAccessibleCheckBox::IsChecked() const
+{
+ bool bChecked = false;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox && pVCLXCheckBox->getState() == sal_Int16(1) )
+ bChecked = true;
+
+ return bChecked;
+}
+
+
+bool VCLXAccessibleCheckBox::IsIndeterminate() const
+{
+ bool bIndeterminate = false;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox && pVCLXCheckBox->getState() == sal_Int16(2) )
+ bIndeterminate = true;
+
+ return bIndeterminate;
+}
+
+
+void VCLXAccessibleCheckBox::SetChecked( bool bChecked )
+{
+ if ( m_bChecked != bChecked )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bChecked )
+ aOldValue <<= AccessibleStateType::CHECKED;
+ else
+ aNewValue <<= AccessibleStateType::CHECKED;
+ m_bChecked = bChecked;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleCheckBox::SetIndeterminate( bool bIndeterminate )
+{
+ if ( m_bIndeterminate != bIndeterminate )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bIndeterminate )
+ aOldValue <<= AccessibleStateType::INDETERMINATE;
+ else
+ aNewValue <<= AccessibleStateType::INDETERMINATE;
+ m_bIndeterminate = bIndeterminate;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleCheckBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::CheckboxToggle:
+ {
+ SetChecked( IsChecked() );
+ SetIndeterminate( IsIndeterminate() );
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleCheckBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsChecked() )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+
+ if ( IsIndeterminate() )
+ rStateSet.AddState( AccessibleStateType::INDETERMINATE );
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleCheckBox, VCLXAccessibleTextComponent, VCLXAccessibleCheckBox_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleCheckBox, VCLXAccessibleTextComponent, VCLXAccessibleCheckBox_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleCheckBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleCheckBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleCheckBox::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleCheckBox" };
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleCheckBox::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleCheckBox::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pCheckBox && pVCLXCheckBox )
+ {
+ sal_Int32 nValueMax = sal_Int32(1);
+
+ if ( pCheckBox->IsTriStateEnabled() )
+ nValueMax = sal_Int32(2);
+
+ sal_Int32 nValue = static_cast<sal_Int32>(pVCLXCheckBox->getState());
+
+ ++nValue;
+
+ if ( nValue > nValueMax )
+ nValue = 0;
+
+ pVCLXCheckBox->setState( static_cast<sal_Int16>(nValue) );
+ }
+
+ return true;
+}
+
+
+OUString VCLXAccessibleCheckBox::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ if(IsChecked())
+ return AccResId( RID_STR_ACC_ACTION_UNCHECK );
+ else
+ return AccResId( RID_STR_ACC_ACTION_CHECK );
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleCheckBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ KeyEvent aKeyEvent = pWindow->GetActivationKey();
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ if ( aKeyCode.GetCode() != 0 )
+ {
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ if ( aKeyCode.IsShift() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aKeyCode.IsMod1() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
+ if ( aKeyCode.IsMod2() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
+ if ( aKeyCode.IsMod3() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
+ aKeyStroke.KeyCode = aKeyCode.GetCode();
+ aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
+ aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleCheckBox::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox )
+ aValue <<= static_cast<sal_Int32>(pVCLXCheckBox->getState());
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleCheckBox::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
+ if ( pVCLXCheckBox )
+ {
+ sal_Int32 nValue = 0, nValueMin = 0, nValueMax = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+ nValueMax=implGetMaximumValue();
+
+ if ( nValue < nValueMin )
+ nValue = nValueMin;
+ else if ( nValue > nValueMax )
+ nValue = nValueMax;
+
+ pVCLXCheckBox->setState( static_cast<sal_Int16>(nValue) );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleCheckBox::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= implGetMaximumValue();
+
+ return aValue;
+}
+
+sal_Int32 VCLXAccessibleCheckBox::implGetMaximumValue( )
+{
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox && pCheckBox->IsTriStateEnabled() )
+ return 2;
+
+ return 1;
+}
+
+Any VCLXAccessibleCheckBox::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleCheckBox::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblecombobox.cxx b/accessibility/source/standard/vclxaccessiblecombobox.cxx
new file mode 100644
index 000000000..e537f7199
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblecombobox.cxx
@@ -0,0 +1,54 @@
+/* -*- 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 <standard/vclxaccessiblecombobox.hxx>
+#include <vcl/window.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleComboBox::VCLXAccessibleComboBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::COMBOBOX, false)
+{
+}
+
+
+bool VCLXAccessibleComboBox::IsValid() const
+{
+ return GetWindow();
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleComboBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleComboBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleComboBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleComboBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibledropdowncombobox.cxx b/accessibility/source/standard/vclxaccessibledropdowncombobox.cxx
new file mode 100644
index 000000000..97fcebb04
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibledropdowncombobox.cxx
@@ -0,0 +1,73 @@
+/* -*- 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 <standard/vclxaccessibledropdowncombobox.hxx>
+
+#include <toolkit/awt/vclxwindow.hxx>
+#include <vcl/vclevent.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleDropDownComboBox::VCLXAccessibleDropDownComboBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::COMBOBOX, true)
+{
+}
+
+
+bool VCLXAccessibleDropDownComboBox::IsValid() const
+{
+ return GetWindow();
+}
+
+void VCLXAccessibleDropDownComboBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownOpen:
+ case VclEventId::DropdownClose:
+ {
+ break;
+ }
+
+ default:
+ VCLXAccessibleBox::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+// XServiceInfo
+
+OUString VCLXAccessibleDropDownComboBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleDropDownComboBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleDropDownComboBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleDropDownComboBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibledropdownlistbox.cxx b/accessibility/source/standard/vclxaccessibledropdownlistbox.cxx
new file mode 100644
index 000000000..641c1bdc4
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibledropdownlistbox.cxx
@@ -0,0 +1,51 @@
+/* -*- 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 <standard/vclxaccessibledropdownlistbox.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleDropDownListBox::VCLXAccessibleDropDownListBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::LISTBOX, true)
+{
+}
+
+bool VCLXAccessibleDropDownListBox::IsValid() const
+{
+ return GetWindow();
+}
+
+// XServiceInfo
+OUString VCLXAccessibleDropDownListBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleDropDownListBox";
+}
+
+Sequence< OUString > VCLXAccessibleDropDownListBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleDropDownListBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleedit.cxx b/accessibility/source/standard/vclxaccessibleedit.cxx
new file mode 100644
index 000000000..d41c29737
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleedit.cxx
@@ -0,0 +1,608 @@
+/* -*- 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 <standard/vclxaccessibleedit.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/accessibility/AccessibleTextType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <comphelper/string.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/toolkit/edit.hxx>
+#include <vcl/toolkit/vclmedit.hxx>
+#include <vcl/textdata.hxx>
+#include <vcl/txtattr.hxx>
+#include <vcl/xtextedt.hxx>
+#include <sot/exchange.hxx>
+#include <sot/formats.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleEdit
+
+
+VCLXAccessibleEdit::VCLXAccessibleEdit( VCLXWindow* pVCLWindow )
+ :VCLXAccessibleTextComponent( pVCLWindow )
+{
+ m_nCaretPosition = getCaretPosition();
+}
+
+
+void VCLXAccessibleEdit::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::EditModify:
+ {
+ SetText( implGetText() );
+ }
+ break;
+ case VclEventId::EditCaretChanged:
+ {
+ sal_Int32 nOldCaretPosition = m_nCaretPosition;
+ m_nCaretPosition = getCaretPosition();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if (pWindow && pWindow->HasChildPathFocus())
+ {
+ if (m_nCaretPosition != nOldCaretPosition)
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= nOldCaretPosition;
+ aNewValue <<= m_nCaretPosition;
+ NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ }
+ break;
+ case VclEventId::EditSelectionChanged:
+ {
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if (pWindow && pWindow->HasChildPathFocus())
+ {
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED, Any(), Any() );
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ rStateSet.AddState( AccessibleStateType::SINGLE_LINE );
+ if ( pVCLXEdit->isEditable() )
+ rStateSet.AddState( AccessibleStateType::EDITABLE );
+ }
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleEdit::implGetText()
+{
+ OUString aText;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ aText = OutputDevice::GetNonMnemonicString( pEdit->GetText() );
+
+ if ( implGetAccessibleRole() == AccessibleRole::PASSWORD_TEXT )
+ {
+ sal_Unicode cEchoChar = pEdit->GetEchoChar();
+ if ( !cEchoChar )
+ cEchoChar = '*';
+ OUStringBuffer sTmp(aText.getLength());
+ aText = comphelper::string::padToLength(sTmp, aText.getLength(),
+ cEchoChar).makeStringAndClear();
+ }
+ }
+
+ return aText;
+}
+
+
+void VCLXAccessibleEdit::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ awt::Selection aSelection;
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit )
+ aSelection = pVCLXEdit->getSelection();
+
+ nStartIndex = aSelection.Min;
+ nEndIndex = aSelection.Max;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleEdit::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleEdit";
+}
+
+
+Sequence< OUString > VCLXAccessibleEdit::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleEdit" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleEdit::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+Reference< XAccessible > VCLXAccessibleEdit::getAccessibleChild( sal_Int32 )
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+sal_Int16 VCLXAccessibleEdit::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetAccessibleRole();
+}
+
+sal_Int16 VCLXAccessibleEdit::implGetAccessibleRole( )
+{
+ sal_Int16 nRole;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit && ( pEdit->IsPassword() || pEdit->GetEchoChar() ) )
+ nRole = AccessibleRole::PASSWORD_TEXT;
+ else if ( pEdit && ( pEdit->GetStyle() & WB_READONLY ) )
+ nRole = AccessibleRole::STATIC;
+ else
+ nRole = AccessibleRole::TEXT;
+
+ return nRole;
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleEdit::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ // There is one action: activate
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleEdit::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ bool bDoAction = false;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->GrabFocus();
+ bDoAction = true;
+ }
+
+ return bDoAction;
+}
+
+
+OUString VCLXAccessibleEdit::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0)
+ throw IndexOutOfBoundsException();
+
+ return "activate";
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleEdit::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessibleKeyBinding >();
+}
+
+
+// XAccessibleText
+
+
+sal_Int32 VCLXAccessibleEdit::getCaretPosition( )
+{
+ return getSelectionEnd();
+}
+
+
+sal_Bool VCLXAccessibleEdit::setCaretPosition( sal_Int32 nIndex )
+{
+ return setSelection( nIndex, nIndex );
+}
+
+
+sal_Unicode VCLXAccessibleEdit::getCharacter( sal_Int32 nIndex )
+{
+ return VCLXAccessibleTextComponent::getCharacter( nIndex );
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleEdit::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+ Sequence< PropertyValue > aProperties = VCLXAccessibleTextComponent::getCharacterAttributes( nIndex, aRequestedAttributes );
+ auto aNonConstRange = asNonConstRange(aProperties);
+
+ // Handle multiline edit character properties
+ VclPtr<VclMultiLineEdit> pMulitLineEdit = GetAsDynamic< VclMultiLineEdit >();
+ if ( pMulitLineEdit )
+ {
+ ExtTextEngine* pTextEngine = pMulitLineEdit->GetTextEngine();
+ TextPaM aCursor( 0, nIndex );
+ const TextAttribFontColor* pFontColor = static_cast<const TextAttribFontColor* >(pTextEngine->FindAttrib( aCursor, TEXTATTR_FONTCOLOR ));
+ if ( pFontColor )
+ {
+ for (PropertyValue& aValue : aNonConstRange )
+ {
+ if (aValue.Name == "CharColor")
+ {
+ aValue.Value <<= pFontColor->GetColor().GetRGBColor();
+ break;
+ }
+ }
+ }
+ }
+
+ // Set default character color if it is not set yet to a valid value
+ for (PropertyValue& aValue : aNonConstRange )
+ {
+ if (aValue.Name == "CharColor")
+ {
+ if ( aValue.Value == sal_Int32(-1) )
+ {
+ OutputDevice* pDev = Application::GetDefaultDevice();
+ if ( pDev )
+ {
+ aValue.Value <<= pDev->GetSettings().GetStyleSettings().GetFieldTextColor();
+ }
+ }
+ break;
+ }
+ }
+
+ return aProperties;
+}
+
+
+awt::Rectangle VCLXAccessibleEdit::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ sal_Int32 nLength = implGetText().getLength();
+
+ if ( !implIsValidRange( nIndex, nIndex, nLength ) )
+ throw IndexOutOfBoundsException();
+
+ VclPtr< Control > pControl = GetAs< Control >();
+ if ( pControl )
+ {
+ if ( nIndex == nLength )
+ {
+ // #108914# calculate virtual bounding rectangle
+ for ( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ tools::Rectangle aRect = pControl->GetCharacterBounds( i );
+ sal_Int32 nHeight = aRect.GetHeight();
+ if ( aBounds.Height < nHeight )
+ {
+ aBounds.Y = aRect.Top();
+ aBounds.Height = nHeight;
+ }
+ if ( i == nLength - 1 )
+ {
+ aBounds.X = aRect.Right() + 1;
+ aBounds.Width = 1;
+ }
+ }
+ }
+ else
+ {
+ aBounds = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
+ }
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getCharacterCount( )
+{
+ return VCLXAccessibleTextComponent::getCharacterCount();
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getIndexAtPoint( const awt::Point& aPoint )
+{
+ return VCLXAccessibleTextComponent::getIndexAtPoint( aPoint );
+}
+
+
+OUString VCLXAccessibleEdit::getSelectedText( )
+{
+ return VCLXAccessibleTextComponent::getSelectedText();
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getSelectionStart( )
+{
+ return VCLXAccessibleTextComponent::getSelectionStart();
+}
+
+
+sal_Int32 VCLXAccessibleEdit::getSelectionEnd( )
+{
+ return VCLXAccessibleTextComponent::getSelectionEnd();
+}
+
+
+sal_Bool VCLXAccessibleEdit::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pVCLXEdit && pEdit && pEdit->IsEnabled() )
+ {
+ pVCLXEdit->setSelection( awt::Selection( nStartIndex, nEndIndex ) );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+OUString VCLXAccessibleEdit::getText( )
+{
+ return VCLXAccessibleTextComponent::getText();
+}
+
+
+OUString VCLXAccessibleEdit::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return VCLXAccessibleTextComponent::getTextRange( nStartIndex, nEndIndex );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleEdit::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+ // Override general text component behavior: MultiLineEdit can have more text portions
+ if ( aTextType == AccessibleTextType::ATTRIBUTE_RUN )
+ {
+ VclPtr<VclMultiLineEdit> pMulitLineEdit = GetAsDynamic< VclMultiLineEdit >();
+ if ( pMulitLineEdit )
+ {
+ ExtTextEngine* pTextEngine = pMulitLineEdit->GetTextEngine();
+ TextPaM aCursor( 0, nIndex );
+ TextSegment aResult;
+ pTextEngine->GetTextPortionRange( aCursor, aResult.SegmentStart, aResult.SegmentEnd );
+ return aResult;
+ }
+ }
+
+ return VCLXAccessibleTextComponent::getTextAtIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleEdit::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ return VCLXAccessibleTextComponent::getTextBeforeIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleEdit::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ return VCLXAccessibleTextComponent::getTextBehindIndex( nIndex, aTextType );
+}
+
+
+sal_Bool VCLXAccessibleEdit::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return VCLXAccessibleTextComponent::copyText( nStartIndex, nEndIndex );
+}
+
+sal_Bool VCLXAccessibleEdit::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+// XAccessibleEditableText
+
+
+sal_Bool VCLXAccessibleEdit::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return copyText( nStartIndex, nEndIndex ) && deleteText( nStartIndex, nEndIndex );
+}
+
+
+sal_Bool VCLXAccessibleEdit::pasteText( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( GetWindow() )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow()->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ Reference< datatransfer::XTransferable > xDataObj;
+ {
+ SolarMutexReleaser aReleaser;
+ xDataObj = xClipboard->getContents();
+ }
+ if ( xDataObj.is() )
+ {
+ datatransfer::DataFlavor aFlavor;
+ SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
+ if ( xDataObj->isDataFlavorSupported( aFlavor ) )
+ {
+ Any aData = xDataObj->getTransferData( aFlavor );
+ OUString sText;
+ aData >>= sText;
+ bReturn = replaceText( nIndex, nIndex, sText );
+ }
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+
+sal_Bool VCLXAccessibleEdit::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ return replaceText( nStartIndex, nEndIndex, OUString() );
+}
+
+
+sal_Bool VCLXAccessibleEdit::insertText( const OUString& sText, sal_Int32 nIndex )
+{
+ return replaceText( nIndex, nIndex, sText );
+}
+
+
+sal_Bool VCLXAccessibleEdit::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ sal_Int32 nMinIndex = std::min( nStartIndex, nEndIndex );
+ sal_Int32 nMaxIndex = std::max( nStartIndex, nEndIndex );
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit && pVCLXEdit->isEditable() )
+ {
+ pVCLXEdit->setText( sText.replaceAt( nMinIndex, nMaxIndex - nMinIndex, sReplacement ) );
+ sal_Int32 nIndex = nMinIndex + sReplacement.getLength();
+ setSelection( nIndex, nIndex );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+sal_Bool VCLXAccessibleEdit::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const Sequence<PropertyValue>& )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false; // attributes cannot be set for an edit
+}
+
+
+sal_Bool VCLXAccessibleEdit::setText( const OUString& sText )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
+ if ( pVCLXEdit && pVCLXEdit->isEditable() )
+ {
+ pVCLXEdit->setText( sText );
+ sal_Int32 nSize = sText.getLength();
+ pVCLXEdit->setSelection( awt::Selection( nSize, nSize ) );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx b/accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx
new file mode 100644
index 000000000..9e2874365
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblefixedhyperlink.cxx
@@ -0,0 +1,38 @@
+/* -*- 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 <standard/vclxaccessiblefixedhyperlink.hxx>
+
+using namespace ::com::sun::star;
+
+// VCLXAccessibleFixedHyperlink
+
+// XServiceInfo
+
+OUString VCLXAccessibleFixedHyperlink::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleFixedHyperlink";
+}
+
+uno::Sequence<OUString> VCLXAccessibleFixedHyperlink::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleFixedHyperlink" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblefixedtext.cxx b/accessibility/source/standard/vclxaccessiblefixedtext.cxx
new file mode 100644
index 000000000..b62faded5
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblefixedtext.cxx
@@ -0,0 +1,54 @@
+/* -*- 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 <standard/vclxaccessiblefixedtext.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/window.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+
+// VCLXAccessibleFixedText
+
+void VCLXAccessibleFixedText::FillAccessibleStateSet(utl::AccessibleStateSetHelper& rStateSet)
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet(rStateSet);
+
+ if (GetWindow() && GetWindow()->GetStyle() & WB_WORDBREAK)
+ rStateSet.AddState(AccessibleStateType::MULTI_LINE);
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleFixedText::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleFixedText";
+}
+
+Sequence<OUString> VCLXAccessibleFixedText::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleFixedText" };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleheaderbar.cxx b/accessibility/source/standard/vclxaccessibleheaderbar.cxx
new file mode 100644
index 000000000..de5208b35
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleheaderbar.cxx
@@ -0,0 +1,130 @@
+/* -*- 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 <standard/vclxaccessibleheaderbar.hxx>
+#include <standard/vclxaccessibleheaderbaritem.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <vcl/headbar.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+VCLXAccessibleHeaderBar::VCLXAccessibleHeaderBar(VCLXWindow* pVCLWindow)
+ : VCLXAccessibleComponent(pVCLWindow)
+{
+ m_pHeadBar = GetAs<HeaderBar>();
+}
+
+VCLXAccessibleHeaderBar::~VCLXAccessibleHeaderBar() {}
+
+// XServiceInfo
+
+OUString VCLXAccessibleHeaderBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleHeaderBar";
+}
+
+Sequence<OUString> VCLXAccessibleHeaderBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleHeaderBar" };
+}
+
+// =======XAccessibleContext=======
+
+sal_Int32 SAL_CALL VCLXAccessibleHeaderBar::getAccessibleChildCount()
+{
+ SolarMutexGuard g;
+
+ sal_Int32 nCount = 0;
+ if (m_pHeadBar)
+ nCount = m_pHeadBar->GetItemCount();
+
+ return nCount;
+}
+css::uno::Reference<css::accessibility::XAccessible>
+ SAL_CALL VCLXAccessibleHeaderBar::getAccessibleChild(sal_Int32 i)
+{
+ SolarMutexGuard g;
+
+ if (i < 0 || i >= getAccessibleChildCount())
+ throw IndexOutOfBoundsException();
+
+ Reference<XAccessible> xChild;
+ // search for the child
+ if (o3tl::make_unsigned(i) >= m_aAccessibleChildren.size())
+ xChild = CreateChild(i);
+ else
+ {
+ xChild = m_aAccessibleChildren[i];
+ if (!xChild.is())
+ xChild = CreateChild(i);
+ }
+ return xChild;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleHeaderBar::getAccessibleRole()
+{
+ return css::accessibility::AccessibleRole::LIST;
+}
+
+void SAL_CALL VCLXAccessibleHeaderBar::disposing()
+{
+ SolarMutexGuard g;
+
+ ListItems().swap(m_aAccessibleChildren);
+ VCLXAccessibleComponent::disposing();
+}
+
+css::uno::Reference<css::accessibility::XAccessible>
+VCLXAccessibleHeaderBar::CreateChild(sal_Int32 i)
+{
+ Reference<XAccessible> xChild;
+
+ sal_uInt16 nPos = static_cast<sal_uInt16>(i);
+ if (nPos >= m_aAccessibleChildren.size())
+ {
+ m_aAccessibleChildren.resize(nPos + 1);
+
+ // insert into the container
+ xChild = new VCLXAccessibleHeaderBarItem(m_pHeadBar, i);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ else
+ {
+ xChild = m_aAccessibleChildren[nPos];
+ // check if position is empty and can be used else we have to adjust all entries behind this
+ if (!xChild.is())
+ {
+ xChild = new VCLXAccessibleHeaderBarItem(m_pHeadBar, i);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ }
+ return xChild;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleheaderbaritem.cxx b/accessibility/source/standard/vclxaccessibleheaderbaritem.cxx
new file mode 100644
index 000000000..5c9bf5c9a
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleheaderbaritem.cxx
@@ -0,0 +1,265 @@
+/* -*- 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 <standard/vclxaccessibleheaderbaritem.hxx>
+
+#include <vcl/headbar.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleHeaderBarItem::VCLXAccessibleHeaderBarItem( HeaderBar* pHeadBar, sal_Int32 _nIndexInParent )
+ :m_pHeadBar( pHeadBar )
+ ,m_nIndexInParent(_nIndexInParent + 1)
+
+{
+}
+
+VCLXAccessibleHeaderBarItem::~VCLXAccessibleHeaderBarItem()
+{
+}
+
+void VCLXAccessibleHeaderBarItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ if ( m_pHeadBar )
+ {
+ if ( m_pHeadBar->IsEnabled() )
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+
+ if ( m_pHeadBar->IsVisible() )
+ {
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+ }
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+ rStateSet.AddState( AccessibleStateType::RESIZABLE );
+ }
+}
+
+// OCommonAccessibleComponent
+awt::Rectangle VCLXAccessibleHeaderBarItem::implGetBounds()
+{
+ awt::Rectangle aBounds;
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pHeadBar )
+ aBounds = AWTRectangle( m_pHeadBar->GetItemRect( sal_uInt16( m_nIndexInParent ) ) );
+
+ return aBounds;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleHeaderBarItem, OAccessibleExtendedComponentHelper, VCLXAccessibleHeaderBarItem_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleHeaderBarItem, OAccessibleExtendedComponentHelper, VCLXAccessibleHeaderBarItem_BASE )
+
+
+// XServiceInfo
+OUString VCLXAccessibleHeaderBarItem::getImplementationName()
+{
+ return "com.sun.star.comp.svtools.AccessibleHeaderBarItem";
+}
+
+sal_Bool VCLXAccessibleHeaderBarItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+Sequence< OUString > VCLXAccessibleHeaderBarItem::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleHeaderBarItem" };
+}
+
+// XAccessible
+Reference< XAccessibleContext > VCLXAccessibleHeaderBarItem::getAccessibleContext()
+{
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+Reference< XAccessible > VCLXAccessibleHeaderBarItem::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessible >();
+}
+
+
+Reference< XAccessible > VCLXAccessibleHeaderBarItem::getAccessibleParent()
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pHeadBar )
+ {
+ xParent = m_pHeadBar->GetAccessible();
+ }
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getAccessibleIndexInParent()
+{
+ OExternalLockGuard aGuard( this );
+ return m_nIndexInParent - 1;
+}
+
+
+sal_Int16 VCLXAccessibleHeaderBarItem::getAccessibleRole()
+{
+ return AccessibleRole::COLUMN_HEADER;
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getAccessibleDescription()
+{
+ return OUString();
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getAccessibleName()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sName;
+ if(m_pHeadBar)
+ sName = m_pHeadBar->GetItemText( sal_uInt16( m_nIndexInParent ) );
+ return sName;
+}
+
+
+Reference< XAccessibleRelationSet > VCLXAccessibleHeaderBarItem::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Reference< XAccessibleStateSet > VCLXAccessibleHeaderBarItem::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+css::lang::Locale VCLXAccessibleHeaderBarItem::getLocale()
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleHeaderBarItem::getAccessibleAtPoint( const awt::Point& )
+{
+ return Reference< XAccessible >();
+}
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getForeground()
+{
+ return 0;
+}
+
+
+sal_Int32 VCLXAccessibleHeaderBarItem::getBackground()
+{
+ return 0;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > VCLXAccessibleHeaderBarItem::getFont()
+{
+ return Reference< awt::XFont >();
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getTitledBorderText()
+{
+ return OUString();
+}
+
+
+OUString VCLXAccessibleHeaderBarItem::getToolTipText()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sText;
+ if ( m_pHeadBar )
+ sText = m_pHeadBar->GetQuickHelpText();
+
+ return sText;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblelist.cxx b/accessibility/source/standard/vclxaccessiblelist.cxx
new file mode 100644
index 000000000..bb81350f5
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblelist.cxx
@@ -0,0 +1,942 @@
+/* -*- 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 <standard/vclxaccessiblelist.hxx>
+#include <standard/vclxaccessiblelistitem.hxx>
+#include <helper/listboxhelper.hxx>
+
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <toolkit/helper/convert.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::accessibility;
+
+namespace
+{
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkSelection_Impl( sal_Int32 _nIndex, const IComboListBoxHelper& _rListBox, bool bSelected )
+ {
+ sal_Int32 nCount = bSelected ? _rListBox.GetSelectedEntryCount()
+ : _rListBox.GetEntryCount();
+ if ( _nIndex < 0 || _nIndex >= nCount )
+ throw css::lang::IndexOutOfBoundsException();
+ }
+}
+
+VCLXAccessibleList::VCLXAccessibleList (VCLXWindow* pVCLWindow, BoxType aBoxType,
+ const Reference< XAccessible >& _xParent)
+ : VCLXAccessibleComponent (pVCLWindow),
+ m_aBoxType (aBoxType),
+ m_nVisibleLineCount (0),
+ m_nIndexInParent (DEFAULT_INDEX_IN_PARENT),
+ m_nLastTopEntry ( 0 ),
+ m_nLastSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
+ m_bDisableProcessEvent ( false ),
+ m_bVisible ( true ),
+ m_nCurSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
+ m_xParent ( _xParent )
+{
+ // Because combo boxes and list boxes don't have a common interface for
+ // methods with identical signature we have to write down twice the
+ // same code.
+ switch (m_aBoxType)
+ {
+ case COMBOBOX:
+ {
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ m_pListBoxHelper.reset( new VCLListBoxHelper<ComboBox> (*pBox) );
+ break;
+ }
+
+ case LISTBOX:
+ {
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ m_pListBoxHelper.reset( new VCLListBoxHelper<ListBox> (*pBox) );
+ break;
+ }
+ }
+ UpdateVisibleLineCount();
+ if(m_pListBoxHelper)
+ {
+ m_nCurSelectedPos=m_pListBoxHelper->GetSelectedEntryPos(0);
+ }
+ sal_uInt16 nCount = static_cast<sal_uInt16>(getAccessibleChildCount());
+ m_aAccessibleChildren.reserve(nCount);
+}
+
+
+void VCLXAccessibleList::SetIndexInParent (sal_Int32 nIndex)
+{
+ m_nIndexInParent = nIndex;
+}
+
+
+void SAL_CALL VCLXAccessibleList::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ // Dispose all items in the list.
+ m_aAccessibleChildren.clear();
+
+ m_pListBoxHelper.reset();
+}
+
+
+void VCLXAccessibleList::FillAccessibleStateSet (utl::AccessibleStateSetHelper& rStateSet)
+{
+ SolarMutexGuard aSolarGuard;
+
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+ // check if our list should be visible
+ if ( m_pListBoxHelper
+ && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN
+ && !m_pListBoxHelper->IsInDropDown() )
+ {
+ rStateSet.RemoveState (AccessibleStateType::VISIBLE);
+ rStateSet.RemoveState (AccessibleStateType::SHOWING);
+ m_bVisible = false;
+ }
+
+ // Both the combo box and list box are handled identical in the
+ // following but for some reason they don't have a common interface for
+ // the methods used.
+ if ( m_pListBoxHelper )
+ {
+ if ( m_pListBoxHelper->IsMultiSelectionEnabled() )
+ rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
+ rStateSet.AddState (AccessibleStateType::FOCUSABLE);
+ // All children are transient.
+ rStateSet.AddState (AccessibleStateType::MANAGES_DESCENDANTS);
+ }
+}
+
+void VCLXAccessibleList::notifyVisibleStates(bool _bSetNew )
+{
+ m_bVisible = _bSetNew;
+ Any aOldValue, aNewValue;
+ (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+
+ ListItems::iterator aIter = m_aAccessibleChildren.begin();
+ UpdateVisibleLineCount();
+ // adjust the index inside the VCLXAccessibleListItem
+ for ( ; aIter != m_aAccessibleChildren.end(); )
+ {
+ Reference< XAccessible > xHold = *aIter;
+ if (!xHold.is())
+ {
+ aIter = m_aAccessibleChildren.erase(aIter);
+ }
+ else
+ {
+ VCLXAccessibleListItem* pItem = static_cast<VCLXAccessibleListItem*>(xHold.get());
+ const sal_Int32 nTopEntry = m_pListBoxHelper ? m_pListBoxHelper->GetTopEntry() : 0;
+ const sal_Int32 nPos = static_cast<sal_Int32>(aIter - m_aAccessibleChildren.begin());
+ bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) );
+ pItem->SetVisible( m_bVisible && bVisible );
+ ++aIter;
+ }
+
+ }
+}
+
+void VCLXAccessibleList::UpdateSelection_Acc (std::u16string_view /*sTextOfSelectedItem*/, bool b_IsDropDownList)
+{
+ if ( m_aBoxType != COMBOBOX )
+ return;
+
+ /* FIXME: is there something missing here? nIndex is unused. Looks like
+ * copy-paste from VCLXAccessibleList::UpdateSelection() */
+ // VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ // if ( pBox )
+ // {
+ // // Find the index of the selected item inside the VCL control...
+ // sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
+ // // ...and then find the associated accessibility object.
+ // if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
+ // nIndex = 0;
+ UpdateSelection_Impl_Acc(b_IsDropDownList);
+ // }
+}
+
+
+void VCLXAccessibleList::UpdateSelection_Impl_Acc(bool bHasDropDownList)
+{
+ uno::Any aOldValue, aNewValue;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ Reference< XAccessible > xNewAcc;
+ if ( m_pListBoxHelper )
+ {
+ sal_Int32 i=0;
+ m_nCurSelectedPos = LISTBOX_ENTRY_NOTFOUND;
+ for ( const auto& rChild : m_aAccessibleChildren )
+ {
+ Reference< XAccessible > xHold = rChild;
+ if ( xHold.is() )
+ {
+ VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >( xHold.get() );
+ // Retrieve the item's index from the list entry.
+ bool bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i);
+ if (bNowSelected)
+ m_nCurSelectedPos = i;
+
+ if ( bNowSelected && !pItem->IsSelected() )
+ {
+ xNewAcc = rChild;
+ aNewValue <<= xNewAcc;
+ }
+ else if ( pItem->IsSelected() )
+ m_nLastSelectedPos = i;
+
+ pItem->SetSelected( bNowSelected );
+ }
+ else
+ { // it could happen that a child was not created before
+ checkEntrySelected(i,aNewValue,xNewAcc);
+ }
+ ++i;
+ }
+ const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
+ if ( i < nCount ) // here we have to check the if any other listbox entry is selected
+ {
+ for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i )
+ ;
+ }
+ if ( xNewAcc.is() && GetWindow()->HasFocus() )
+ {
+ if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND )
+ aOldValue <<= getAccessibleChild( m_nLastSelectedPos );
+ aNewValue <<= xNewAcc;
+ }
+ }
+ }
+
+ if (m_aBoxType == COMBOBOX)
+ {
+ //VCLXAccessibleDropDownComboBox
+ //when in list is dropped down, xText = NULL
+ if (bHasDropDownList && m_pListBoxHelper && m_pListBoxHelper->IsInDropDown())
+ {
+ if ( aNewValue.hasValue() || aOldValue.hasValue() )
+ {
+ NotifyAccessibleEvent(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+
+ NotifyListItem(aNewValue);
+ }
+ }
+ else
+ {
+ //VCLXAccessibleComboBox
+ NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, uno::Any(), uno::Any() );
+ }
+ }
+ else if (m_aBoxType == LISTBOX)
+ {
+ if ( aNewValue.hasValue() || aOldValue.hasValue() )
+ {
+ NotifyAccessibleEvent(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+
+ NotifyListItem(aNewValue);
+ }
+ }
+}
+
+void VCLXAccessibleList::NotifyListItem(css::uno::Any const & val)
+{
+ Reference< XAccessible > xCurItem;
+ val >>= xCurItem;
+ if (xCurItem.is())
+ {
+ VCLXAccessibleListItem* pCurItem = static_cast< VCLXAccessibleListItem* >(xCurItem.get());
+ if (pCurItem)
+ {
+ pCurItem->NotifyAccessibleEvent(AccessibleEventId::SELECTION_CHANGED,Any(),Any());
+ }
+ }
+}
+
+void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent, bool b_IsDropDownList)
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownSelect:
+ case VclEventId::ListboxSelect:
+ if ( !m_bDisableProcessEvent )
+ UpdateSelection_Impl_Acc(b_IsDropDownList);
+ break;
+ case VclEventId::WindowGetFocus:
+ break;
+ case VclEventId::ControlGetFocus:
+ {
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ if (m_aBoxType == COMBOBOX && b_IsDropDownList)
+ {
+ //VCLXAccessibleDropDownComboBox
+ }
+ else if (m_aBoxType == LISTBOX && b_IsDropDownList)
+ {
+ }
+ else if ( m_aBoxType == LISTBOX && !b_IsDropDownList)
+ {
+ if ( m_pListBoxHelper )
+ {
+ uno::Any aOldValue,
+ aNewValue;
+ sal_Int32 nPos = m_nCurSelectedPos; //m_pListBoxHelper->GetSelectedEntryPos();
+
+ if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = m_pListBoxHelper->GetTopEntry();
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ aNewValue <<= CreateChild(nPos);
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
+{
+ // Create a reference to this object to prevent an early release of the
+ // listbox (VclEventId::ObjectDying).
+ Reference< XAccessible > xHoldAlive = this;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::DropdownOpen:
+ notifyVisibleStates(true);
+ break;
+ case VclEventId::DropdownClose:
+ notifyVisibleStates(false);
+ break;
+ case VclEventId::ListboxScrolled:
+ UpdateEntryRange_Impl();
+ break;
+
+ // The selection events VclEventId::ComboboxSelect and
+ // VclEventId::ComboboxDeselect are not handled here because here we
+ // have no access to the edit field. Its text is necessary to
+ // identify the currently selected item.
+
+ case VclEventId::ObjectDying:
+ {
+ dispose();
+
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ break;
+ }
+
+ case VclEventId::ListboxItemRemoved:
+ case VclEventId::ComboboxItemRemoved:
+ case VclEventId::ListboxItemAdded:
+ case VclEventId::ComboboxItemAdded:
+ HandleChangedItemList();
+ break;
+ case VclEventId::ControlGetFocus:
+ {
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ // Added by IBM Symphony Acc team to handle the list item focus when List control get focus
+ bool b_IsDropDownList = true;
+ if (m_pListBoxHelper)
+ b_IsDropDownList = ((m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN);
+ if ( m_aBoxType == LISTBOX && !b_IsDropDownList )
+ {
+ if ( m_pListBoxHelper )
+ {
+ uno::Any aOldValue,
+ aNewValue;
+ sal_Int32 nPos = m_nCurSelectedPos;
+
+ if ( nPos == LISTBOX_ENTRY_NOTFOUND )
+ nPos = m_pListBoxHelper->GetTopEntry();
+ if ( nPos != LISTBOX_ENTRY_NOTFOUND )
+ aNewValue <<= CreateChild(nPos);
+ NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+ }
+ }
+ }
+ break;
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
+ }
+}
+
+ void VCLXAccessibleList::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
+{
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if( m_aBoxType == LISTBOX )
+ {
+ if (m_pListBoxHelper && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) != WB_DROPDOWN)
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pBox->GetAccessible() };
+ rRelationSet.AddRelation( com::sun::star::accessibility::AccessibleRelation( com::sun::star::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
+ }
+ }
+ else
+ {
+ VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet);
+ }
+}
+
+
+/** To find out which item is currently selected and to update the SELECTED
+ state of the associated accessibility objects accordingly we exploit the
+ fact that the
+*/
+void VCLXAccessibleList::UpdateSelection (std::u16string_view sTextOfSelectedItem)
+{
+ if ( m_aBoxType != COMBOBOX )
+ return;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ // Find the index of the selected item inside the VCL control...
+ sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
+ // ...and then find the associated accessibility object.
+ if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
+ nIndex = 0;
+ UpdateSelection_Impl(nIndex);
+ }
+}
+
+
+Reference<XAccessible> VCLXAccessibleList::CreateChild (sal_Int32 nPos)
+{
+ Reference<XAccessible> xChild;
+
+ if ( o3tl::make_unsigned(nPos) >= m_aAccessibleChildren.size() )
+ {
+ m_aAccessibleChildren.resize(nPos + 1);
+
+ // insert into the container
+ xChild = new VCLXAccessibleListItem(nPos, this);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ else
+ {
+ xChild = m_aAccessibleChildren[nPos];
+ // check if position is empty and can be used else we have to adjust all entries behind this
+ if (!xChild.is())
+ {
+ xChild = new VCLXAccessibleListItem(nPos, this);
+ m_aAccessibleChildren[nPos] = xChild;
+ }
+ }
+
+ if ( xChild.is() )
+ {
+ // Just add the SELECTED state.
+ bool bNowSelected = false;
+ if ( m_pListBoxHelper )
+ bNowSelected = m_pListBoxHelper->IsEntryPosSelected(nPos);
+ if (bNowSelected)
+ m_nCurSelectedPos = nPos;
+ VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >(xChild.get());
+ pItem->SetSelected( bNowSelected );
+
+ // Set the child's VISIBLE state.
+ UpdateVisibleLineCount();
+ const sal_Int32 nTopEntry = m_pListBoxHelper ? m_pListBoxHelper->GetTopEntry() : 0;
+ bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) );
+ pItem->SetVisible( m_bVisible && bVisible );
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleList::HandleChangedItemList()
+{
+ m_aAccessibleChildren.clear();
+ NotifyAccessibleEvent (
+ AccessibleEventId::INVALIDATE_ALL_CHILDREN,
+ Any(), Any());
+}
+
+
+IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleList, VCLXAccessibleComponent, VCLXAccessibleList_BASE)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleList, VCLXAccessibleComponent, VCLXAccessibleList_BASE)
+
+// XAccessible
+
+Reference<XAccessibleContext> SAL_CALL
+ VCLXAccessibleList::getAccessibleContext()
+{
+ return this;
+}
+
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleList::getAccessibleChildCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return implGetAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleList::implGetAccessibleChildCount()
+{
+ sal_Int32 nCount = 0;
+ if ( m_pListBoxHelper )
+ nCount = m_pListBoxHelper->GetEntryCount();
+
+ return nCount;
+}
+
+Reference<XAccessible> SAL_CALL VCLXAccessibleList::getAccessibleChild (sal_Int32 i)
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( i < 0 || i >= getAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ // search for the child
+ if ( o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ xChild = CreateChild (i);
+ else
+ {
+ xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ xChild = CreateChild (i);
+ }
+ OSL_ENSURE( xChild.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" );
+ return xChild;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleList::getAccessibleParent( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return m_xParent;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleList::getAccessibleIndexInParent()
+{
+ if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT)
+ return m_nIndexInParent;
+ else
+ return VCLXAccessibleComponent::getAccessibleIndexInParent();
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleList::getAccessibleRole()
+{
+ return AccessibleRole::LIST;
+}
+
+// XServiceInfo
+OUString VCLXAccessibleList::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleList";
+}
+
+Sequence< OUString > VCLXAccessibleList::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleList"});
+}
+
+void VCLXAccessibleList::UpdateVisibleLineCount()
+{
+ if ( m_pListBoxHelper )
+ {
+ if ( (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
+ m_nVisibleLineCount = m_pListBoxHelper->GetDisplayLineCount();
+ else
+ {
+ sal_uInt16 nCols = 0,
+ nLines = 0;
+ m_pListBoxHelper->GetMaxVisColumnsAndLines (nCols, nLines);
+ m_nVisibleLineCount = nLines;
+ }
+ }
+}
+
+void VCLXAccessibleList::UpdateEntryRange_Impl()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_Int32 nTop = m_nLastTopEntry;
+
+ if ( m_pListBoxHelper )
+ nTop = m_pListBoxHelper->GetTopEntry();
+ if ( nTop != m_nLastTopEntry )
+ {
+ UpdateVisibleLineCount();
+ sal_Int32 nBegin = std::min( m_nLastTopEntry, nTop );
+ sal_Int32 nEnd = std::max( m_nLastTopEntry + m_nVisibleLineCount, nTop + m_nVisibleLineCount );
+ for (sal_Int32 i = nBegin; (i <= nEnd); ++i)
+ {
+ bool bVisible = ( i >= nTop && i < ( nTop + m_nVisibleLineCount ) );
+ Reference< XAccessible > xHold;
+ if ( o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ xHold = m_aAccessibleChildren[i];
+ else if ( bVisible )
+ xHold = CreateChild(i);
+
+ if ( xHold.is() )
+ static_cast< VCLXAccessibleListItem* >( xHold.get() )->SetVisible( m_bVisible && bVisible );
+ }
+ }
+
+ m_nLastTopEntry = nTop;
+}
+
+bool VCLXAccessibleList::checkEntrySelected(sal_Int32 _nPos,Any& _rNewValue,Reference< XAccessible >& _rxNewAcc)
+{
+ OSL_ENSURE(m_pListBoxHelper,"Helper is not valid!");
+ bool bNowSelected = false;
+ if ( m_pListBoxHelper )
+ {
+ bNowSelected = m_pListBoxHelper->IsEntryPosSelected (_nPos);
+ if ( bNowSelected )
+ {
+ _rxNewAcc = CreateChild(_nPos);
+ _rNewValue <<= _rxNewAcc;
+ }
+ }
+ return bNowSelected;
+}
+
+
+void VCLXAccessibleList::UpdateSelection_Impl(sal_Int32)
+{
+ uno::Any aOldValue, aNewValue;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ Reference< XAccessible > xNewAcc;
+
+ if ( m_pListBoxHelper )
+ {
+ sal_Int32 i=0;
+ m_nCurSelectedPos = LISTBOX_ENTRY_NOTFOUND;
+ for ( const auto& rChild : m_aAccessibleChildren )
+ {
+ Reference< XAccessible > xHold = rChild;
+ if ( xHold.is() )
+ {
+ VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >( xHold.get() );
+ // Retrieve the item's index from the list entry.
+ bool bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i);
+ if (bNowSelected)
+ m_nCurSelectedPos = i;
+
+ if ( bNowSelected && !pItem->IsSelected() )
+ {
+ xNewAcc = rChild;
+ aNewValue <<= xNewAcc;
+ }
+ else if ( pItem->IsSelected() )
+ m_nLastSelectedPos = i;
+
+ pItem->SetSelected( bNowSelected );
+ }
+ else
+ { // it could happen that a child was not created before
+ checkEntrySelected(i,aNewValue,xNewAcc);
+ }
+ ++i;
+ }
+ const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
+ if ( i < nCount ) // here we have to check the if any other listbox entry is selected
+ {
+ for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i )
+ ;
+ }
+ if ( xNewAcc.is() && GetWindow()->HasFocus() )
+ {
+ if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND )
+ aOldValue <<= getAccessibleChild( m_nLastSelectedPos );
+ aNewValue <<= xNewAcc;
+ }
+ if (m_pListBoxHelper->IsInDropDown())
+ {
+ if ( aNewValue.hasValue() || aOldValue.hasValue() )
+ NotifyAccessibleEvent(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ aOldValue,
+ aNewValue );
+ //the SELECTION_CHANGED is not necessary
+ //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
+ }
+ }
+ }
+}
+
+
+// XAccessibleSelection
+
+void SAL_CALL VCLXAccessibleList::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nChildIndex,*m_pListBoxHelper,false);
+
+ m_pListBoxHelper->SelectEntryPos( static_cast<sal_uInt16>(nChildIndex) );
+ // call the select handler, don't handle events in this time
+ m_bDisableProcessEvent = true;
+ m_pListBoxHelper->Select();
+ m_bDisableProcessEvent = false;
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+sal_Bool SAL_CALL VCLXAccessibleList::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ bool bRet = false;
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nChildIndex,*m_pListBoxHelper,false);
+
+ bRet = m_pListBoxHelper->IsEntryPosSelected( static_cast<sal_uInt16>(nChildIndex) );
+ }
+ return bRet;
+}
+
+void SAL_CALL VCLXAccessibleList::clearAccessibleSelection( )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ m_pListBoxHelper->SetNoSelection();
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+void SAL_CALL VCLXAccessibleList::selectAllAccessibleChildren( )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ m_pListBoxHelper->SelectEntryPos( i );
+ // call the select handler, don't handle events in this time
+ m_bDisableProcessEvent = true;
+ m_pListBoxHelper->Select();
+ m_bDisableProcessEvent = false;
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleList::getSelectedAccessibleChildCount( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_Int32 nCount = 0;
+ if ( m_pListBoxHelper )
+ nCount = m_pListBoxHelper->GetSelectedEntryCount();
+ return nCount;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleList::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,true);
+ return getAccessibleChild( m_pListBoxHelper->GetSelectedEntryPos( static_cast<sal_uInt16>(nSelectedChildIndex) ) );
+ }
+
+ return nullptr;
+}
+
+void SAL_CALL VCLXAccessibleList::deselectAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ bool bNotify = false;
+
+ {
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if ( m_pListBoxHelper )
+ {
+ checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,false);
+
+ m_pListBoxHelper->SelectEntryPos( static_cast<sal_uInt16>(nSelectedChildIndex), false );
+ // call the select handler, don't handle events in this time
+ m_bDisableProcessEvent = true;
+ m_pListBoxHelper->Select();
+ m_bDisableProcessEvent = false;
+ bNotify = true;
+ }
+ }
+
+ if ( bNotify )
+ UpdateSelection_Impl();
+}
+
+awt::Rectangle VCLXAccessibleList::implGetBounds()
+{
+ awt::Rectangle aBounds ( 0, 0, 0, 0 );
+ if ( m_pListBoxHelper
+ && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
+ {
+ if ( m_pListBoxHelper->IsInDropDown() )
+ aBounds = AWTRectangle(m_pListBoxHelper->GetDropDownPosSizePixel());
+ }
+ else
+ {
+ // a list has the same bounds as his parent but starts at (0,0)
+ aBounds = VCLXAccessibleComponent::implGetBounds();
+ aBounds.X = 0;
+ aBounds.Y = 0;
+ if ( m_aBoxType == COMBOBOX )
+ {
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ Size aSize = pBox->GetSubEdit()->GetSizePixel();
+ aBounds.Y += aSize.Height();
+ aBounds.Height -= aSize.Height();
+ }
+ }
+ }
+ return aBounds;
+}
+
+
+awt::Point VCLXAccessibleList::getLocationOnScreen( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ awt::Point aPos;
+ if ( m_pListBoxHelper
+ && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
+ {
+ if ( m_pListBoxHelper->IsInDropDown() )
+ aPos = AWTPoint(m_pListBoxHelper->GetDropDownPosSizePixel().TopLeft());
+ }
+ else
+ {
+ aPos = VCLXAccessibleComponent::getLocationOnScreen();
+ if ( m_aBoxType == COMBOBOX )
+ {
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ aPos.Y += pBox->GetSubEdit()->GetSizePixel().Height();
+ }
+ }
+ }
+ return aPos;
+}
+
+
+bool VCLXAccessibleList::IsInDropDown() const
+{
+ return m_pListBoxHelper->IsInDropDown();
+}
+
+
+void VCLXAccessibleList::HandleDropOpen()
+{
+ if ( !m_bDisableProcessEvent )
+ UpdateSelection_Impl();
+ if (m_nCurSelectedPos != LISTBOX_ENTRY_NOTFOUND &&
+ m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND)
+ {
+ Reference< XAccessible > xChild = getAccessibleChild(m_nCurSelectedPos);
+ if(xChild.is())
+ {
+ uno::Any aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, uno::Any(), aNewValue );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblelistbox.cxx b/accessibility/source/standard/vclxaccessiblelistbox.cxx
new file mode 100644
index 000000000..4b5ed9377
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblelistbox.cxx
@@ -0,0 +1,53 @@
+/* -*- 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 <standard/vclxaccessiblelistbox.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+
+VCLXAccessibleListBox::VCLXAccessibleListBox (VCLXWindow* pVCLWindow)
+ : VCLXAccessibleBox (pVCLWindow, VCLXAccessibleBox::LISTBOX, false)
+{
+}
+
+
+bool VCLXAccessibleListBox::IsValid() const
+{
+ return GetWindow();
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleListBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleListBox";
+}
+
+
+Sequence< OUString > VCLXAccessibleListBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleBox::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleListBox"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblelistitem.cxx b/accessibility/source/standard/vclxaccessiblelistitem.cxx
new file mode 100644
index 000000000..81a5cd1a2
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblelistitem.cxx
@@ -0,0 +1,617 @@
+/* -*- 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 <standard/vclxaccessiblelistitem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/IComboListBoxHelper.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/settings.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <comphelper/accessibleeventnotifier.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+namespace
+{
+ /// @throws css::lang::IndexOutOfBoundsException
+ void checkIndex_Impl( sal_Int32 _nIndex, const OUString& _sText )
+ {
+ if ( _nIndex < 0 || _nIndex > _sText.getLength() )
+ throw css::lang::IndexOutOfBoundsException();
+ }
+}
+
+// class VCLXAccessibleListItem ------------------------------------------
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+
+
+// Ctor() and Dtor()
+
+VCLXAccessibleListItem::VCLXAccessibleListItem(sal_Int32 _nIndexInParent, rtl::Reference< VCLXAccessibleList > _xParent)
+ : VCLXAccessibleListItem_BASE(m_aMutex)
+ , m_nIndexInParent(_nIndexInParent)
+ , m_bSelected(false)
+ , m_bVisible(false)
+ , m_nClientId(0)
+ , m_xParent(std::move(_xParent))
+{
+ assert(m_xParent.is());
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent->getListBoxHelper();
+ if (pListBoxHelper)
+ m_sEntryText = pListBoxHelper->GetEntry(static_cast<sal_uInt16>(_nIndexInParent));
+}
+
+void VCLXAccessibleListItem::SetSelected( bool _bSelected )
+{
+ if ( m_bSelected != _bSelected )
+ {
+ Any aOldValue;
+ Any aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = _bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleListItem::SetVisible( bool _bVisible )
+{
+ if ( m_bVisible != _bVisible )
+ {
+ Any aOldValue, aNewValue;
+ m_bVisible = _bVisible;
+ (_bVisible ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ (_bVisible ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleListItem::NotifyAccessibleEvent( sal_Int16 _nEventId,
+ const css::uno::Any& _aOldValue,
+ const css::uno::Any& _aNewValue )
+{
+ AccessibleEventObject aEvt;
+ aEvt.Source = *this;
+ aEvt.EventId = _nEventId;
+ aEvt.OldValue = _aOldValue;
+ aEvt.NewValue = _aNewValue;
+
+ if (m_nClientId)
+ comphelper::AccessibleEventNotifier::addEvent( m_nClientId, aEvt );
+}
+
+// OCommonAccessibleText
+
+OUString VCLXAccessibleListItem::implGetText()
+{
+ return m_sEntryText;
+}
+
+Locale VCLXAccessibleListItem::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+void VCLXAccessibleListItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+// XTypeProvider
+
+Sequence< sal_Int8 > VCLXAccessibleListItem::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+// XComponent
+
+void SAL_CALL VCLXAccessibleListItem::disposing()
+{
+ comphelper::AccessibleEventNotifier::TClientId nId( 0 );
+ Reference< XInterface > xEventSource;
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ VCLXAccessibleListItem_BASE::disposing();
+ m_sEntryText.clear();
+ m_xParent = nullptr;
+
+ nId = m_nClientId;
+ m_nClientId = 0;
+ if ( nId )
+ xEventSource = *this;
+ }
+
+ // Send a disposing to all listeners.
+ if ( nId )
+ comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleListItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleListItem";
+}
+
+sal_Bool VCLXAccessibleListItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > VCLXAccessibleListItem::getSupportedServiceNames()
+{
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.accessibility.AccessibleListItem"};
+}
+
+// XAccessible
+
+Reference< XAccessibleContext > SAL_CALL VCLXAccessibleListItem::getAccessibleContext( )
+{
+ return this;
+}
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getAccessibleChildCount( )
+{
+ return 0;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleChild( sal_Int32 )
+{
+ return Reference< XAccessible >();
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleParent( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_xParent;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getAccessibleIndexInParent( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_nIndexInParent;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleListItem::getAccessibleRole( )
+{
+ return AccessibleRole::LIST_ITEM;
+ // return AccessibleRole::LABEL;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getAccessibleDescription( )
+{
+ // no description for every item
+ return OUString();
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getAccessibleName( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // entry text == accessible name
+ return m_sEntryText;
+}
+
+Reference< XAccessibleRelationSet > SAL_CALL VCLXAccessibleListItem::getAccessibleRelationSet( )
+{
+ return new utl::AccessibleRelationSetHelper;
+}
+
+Reference< XAccessibleStateSet > SAL_CALL VCLXAccessibleListItem::getAccessibleStateSet( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
+
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper && pListBoxHelper->IsEnabled())
+ {
+ pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
+ }
+
+ if ( m_bSelected )
+ pStateSetHelper->AddState( AccessibleStateType::SELECTED );
+ if ( m_bVisible )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ }
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+Locale SAL_CALL VCLXAccessibleListItem::getLocale( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return implGetLocale();
+}
+
+// XAccessibleComponent
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::containsPoint( const awt::Point& _aPoint )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ bool bInside = false;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aRect(pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent)));
+ aRect.Move(-aRect.Left(), -aRect.Top());
+ bInside = aRect.Contains( VCLPoint( _aPoint ) );
+ }
+ return bInside;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleListItem::getAccessibleAtPoint( const awt::Point& )
+{
+ return Reference< XAccessible >();
+}
+
+awt::Rectangle SAL_CALL VCLXAccessibleListItem::getBounds( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ awt::Rectangle aRect;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ aRect = AWTRectangle(pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent)));
+
+ return aRect;
+}
+
+awt::Point SAL_CALL VCLXAccessibleListItem::getLocation( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Point aPoint(0,0);
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aRect = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) );
+ aPoint = aRect.TopLeft();
+ }
+ return AWTPoint( aPoint );
+}
+
+awt::Point SAL_CALL VCLXAccessibleListItem::getLocationOnScreen( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Point aPoint(0,0);
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aRect = pListBoxHelper->GetBoundingRectangle(static_cast<sal_uInt16>(m_nIndexInParent));
+ aPoint = aRect.TopLeft();
+ aPoint += pListBoxHelper->GetWindowExtentsRelative().TopLeft();
+ }
+ return AWTPoint( aPoint );
+}
+
+awt::Size SAL_CALL VCLXAccessibleListItem::getSize( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Size aSize;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ aSize = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) ).GetSize();
+
+ return AWTSize( aSize );
+}
+
+void SAL_CALL VCLXAccessibleListItem::grabFocus( )
+{
+ // no focus for each item
+}
+
+// XAccessibleText
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getCaretPosition()
+{
+ return -1;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::setCaretPosition( sal_Int32 nIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidRange( nIndex, nIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+sal_Unicode SAL_CALL VCLXAccessibleListItem::getCharacter( sal_Int32 nIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::implGetCharacter( m_sEntryText, nIndex );
+}
+
+Sequence< PropertyValue > SAL_CALL VCLXAccessibleListItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidIndex( nIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return Sequence< PropertyValue >();
+}
+
+awt::Rectangle SAL_CALL VCLXAccessibleListItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidIndex( nIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ tools::Rectangle aCharRect = pListBoxHelper->GetEntryCharacterBounds( m_nIndexInParent, nIndex );
+ tools::Rectangle aItemRect = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getCharacterCount()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_sEntryText.getLength();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nIndex = -1;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
+ tools::Rectangle aItemRect = pListBoxHelper->GetBoundingRectangle( static_cast<sal_uInt16>(m_nIndexInParent) );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ sal_Int32 nI = pListBoxHelper->GetIndexForPoint( aPnt, nPos );
+ if ( nI != -1 && m_nIndexInParent == nPos )
+ nIndex = nI;
+ }
+ return nIndex;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getSelectedText()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OUString();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getSelectionStart()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return 0;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getSelectionEnd()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return 0;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, m_sEntryText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getText()
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_sEntryText;
+}
+
+OUString SAL_CALL VCLXAccessibleListItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::implGetTextRange( m_sEntryText, nStartIndex, nEndIndex );
+}
+
+css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
+}
+
+css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
+}
+
+css::accessibility::TextSegment SAL_CALL VCLXAccessibleListItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
+}
+
+sal_Bool SAL_CALL VCLXAccessibleListItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ checkIndex_Impl( nStartIndex, m_sEntryText );
+ checkIndex_Impl( nEndIndex, m_sEntryText );
+
+ bool bRet = false;
+ ::accessibility::IComboListBoxHelper* pListBoxHelper = m_xParent.is() ? m_xParent->getListBoxHelper() : nullptr;
+ if (pListBoxHelper)
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = pListBoxHelper->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( getTextRange( nStartIndex, nEndIndex ) );
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+sal_Bool VCLXAccessibleListItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+// XAccessibleEventBroadcaster
+
+void SAL_CALL VCLXAccessibleListItem::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+{
+ if (xListener.is())
+ {
+ if (!m_nClientId)
+ m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
+ comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
+ }
+}
+
+void SAL_CALL VCLXAccessibleListItem::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
+{
+ if ( !(xListener.is() && m_nClientId) )
+ return;
+
+ sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
+ if ( nListenerCount )
+ return;
+
+ // 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
+ if ( m_nClientId )
+ {
+ comphelper::AccessibleEventNotifier::TClientId nId( m_nClientId );
+ m_nClientId = 0;
+ comphelper::AccessibleEventNotifier::revokeClient( nId );
+ }
+}
+
+
+// AF (Oct. 29 2002): Return black as constant foreground color. This is an
+// initial implementation and has to be substituted by code that determines
+// the color that is actually used.
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getForeground()
+{
+ return sal_Int32(COL_BLACK);
+}
+
+// AF (Oct. 29 2002): Return white as constant background color. This is an
+// initial implementation and has to be substituted by code that determines
+// the color that is actually used.
+sal_Int32 SAL_CALL VCLXAccessibleListItem::getBackground()
+{
+ return sal_Int32(COL_WHITE);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenu.cxx b/accessibility/source/standard/vclxaccessiblemenu.cxx
new file mode 100644
index 000000000..a7e31094b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenu.cxx
@@ -0,0 +1,233 @@
+/* -*- 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 <standard/vclxaccessiblemenu.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/menu.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleMenu
+
+
+bool VCLXAccessibleMenu::IsFocused()
+{
+ bool bFocused = false;
+
+ if ( IsHighlighted() && !IsChildHighlighted() )
+ bFocused = true;
+
+ return bFocused;
+}
+
+
+bool VCLXAccessibleMenu::IsPopupMenuOpen()
+{
+ bool bPopupMenuOpen = false;
+
+ if ( m_pParent )
+ {
+ PopupMenu* pPopupMenu = m_pParent->GetPopupMenu( m_pParent->GetItemId( m_nItemPos ) );
+ if ( pPopupMenu && pPopupMenu->IsMenuVisible() )
+ bPopupMenuOpen = true;
+ }
+
+ return bPopupMenuOpen;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleMenu, VCLXAccessibleMenuItem, VCLXAccessibleMenu_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleMenu, VCLXAccessibleMenuItem, VCLXAccessibleMenu_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleMenu::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenu";
+}
+
+
+Sequence< OUString > VCLXAccessibleMenu::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenu" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleMenu::getAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildCount();
+}
+
+
+Reference< XAccessible > VCLXAccessibleMenu::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return GetChild( i );
+}
+
+
+sal_Int16 VCLXAccessibleMenu::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::MENU;
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleMenu::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetChildAt( rPoint );
+}
+
+
+// XAccessibleSelection
+
+
+void VCLXAccessibleMenu::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ SelectChild( nChildIndex );
+}
+
+
+sal_Bool VCLXAccessibleMenu::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ return IsChildSelected( nChildIndex );
+}
+
+
+void VCLXAccessibleMenu::clearAccessibleSelection( )
+{
+ OExternalLockGuard aGuard( this );
+
+ DeSelectAll();
+}
+
+
+void VCLXAccessibleMenu::selectAllAccessibleChildren( )
+{
+ // This method makes no sense in a menu, and so does nothing.
+}
+
+
+sal_Int32 VCLXAccessibleMenu::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetSelectedAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleMenu::implGetSelectedAccessibleChildCount( )
+{
+ sal_Int32 nRet = 0;
+
+ for ( sal_Int32 i = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+Reference< XAccessible > VCLXAccessibleMenu::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( sal_Int32 i = 0, j = 0, nCount = GetChildCount(); i < nCount; i++ )
+ {
+ if ( IsChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
+ {
+ xChild = GetChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleMenu::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
+ throw IndexOutOfBoundsException();
+
+ DeSelectAll();
+}
+
+
+OUString VCLXAccessibleMenu::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
+ throw IndexOutOfBoundsException();
+
+ return OUString( );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenubar.cxx b/accessibility/source/standard/vclxaccessiblemenubar.cxx
new file mode 100644
index 000000000..27a02607b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenubar.cxx
@@ -0,0 +1,187 @@
+/* -*- 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 <standard/vclxaccessiblemenubar.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/settings.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleMenuBar::VCLXAccessibleMenuBar( Menu* pMenu )
+ :OAccessibleMenuComponent( pMenu )
+{
+ if ( pMenu )
+ {
+ m_pWindow = pMenu->GetWindow();
+
+ if ( m_pWindow )
+ m_pWindow->AddEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+ }
+}
+
+
+VCLXAccessibleMenuBar::~VCLXAccessibleMenuBar()
+{
+ if ( m_pWindow )
+ m_pWindow->RemoveEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+}
+
+
+bool VCLXAccessibleMenuBar::IsFocused()
+{
+ bool bFocused = false;
+
+ if ( m_pWindow && m_pWindow->HasFocus() && !IsChildHighlighted() )
+ bFocused = true;
+
+ return bFocused;
+}
+
+
+IMPL_LINK( VCLXAccessibleMenuBar, WindowEventListener, VclWindowEvent&, rEvent, void )
+{
+ OSL_ENSURE( rEvent.GetWindow(), "VCLXAccessibleMenuBar::WindowEventListener: no window!" );
+ if ( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || ( rEvent.GetId() == VclEventId::ObjectDying ) )
+ {
+ ProcessWindowEvent( rEvent );
+ }
+}
+
+
+void VCLXAccessibleMenuBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowGetFocus:
+ case VclEventId::WindowLoseFocus:
+ {
+ SetFocused( rVclWindowEvent.GetId() == VclEventId::WindowGetFocus );
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pWindow )
+ {
+ m_pWindow->RemoveEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+ m_pWindow = nullptr;
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleMenuBar::disposing()
+{
+ OAccessibleMenuComponent::disposing();
+
+ if ( m_pWindow )
+ {
+ m_pWindow->RemoveEventListener( LINK( this, VCLXAccessibleMenuBar, WindowEventListener ) );
+ m_pWindow = nullptr;
+ }
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleMenuBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenuBar";
+}
+
+
+Sequence< OUString > VCLXAccessibleMenuBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenuBar" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleMenuBar::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+
+ if ( m_pMenu )
+ {
+ vcl::Window* pWindow = m_pMenu->GetWindow();
+ if ( pWindow )
+ {
+ vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
+ if ( pParent )
+ {
+ for ( sal_uInt16 n = pParent->GetAccessibleChildWindowCount(); n; )
+ {
+ vcl::Window* pChild = pParent->GetAccessibleChildWindow( --n );
+ if ( pChild == pWindow )
+ {
+ nIndexInParent = n;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return nIndexInParent;
+}
+
+
+sal_Int16 VCLXAccessibleMenuBar::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::MENU_BAR;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+sal_Int32 VCLXAccessibleMenuBar::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return sal_Int32(Application::GetSettings().GetStyleSettings().GetMenuBarColor());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenuitem.cxx b/accessibility/source/standard/vclxaccessiblemenuitem.cxx
new file mode 100644
index 000000000..96e31c007
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenuitem.cxx
@@ -0,0 +1,579 @@
+/* -*- 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 <standard/vclxaccessiblemenuitem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/settings.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleMenuItem::VCLXAccessibleMenuItem( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu )
+ :OAccessibleMenuItemComponent( pParent, nItemPos, pMenu )
+{
+}
+
+
+bool VCLXAccessibleMenuItem::IsFocused()
+{
+ return IsHighlighted();
+}
+
+
+bool VCLXAccessibleMenuItem::IsSelected()
+{
+ return IsHighlighted();
+}
+
+
+bool VCLXAccessibleMenuItem::IsChecked()
+{
+ bool bChecked = false;
+
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ if ( m_pParent->IsItemChecked( nItemId ) )
+ bChecked = true;
+ }
+
+ return bChecked;
+}
+
+
+bool VCLXAccessibleMenuItem::IsHighlighted()
+{
+ bool bHighlighted = false;
+
+ if ( m_pParent && m_pParent->IsHighlighted( m_nItemPos ) )
+ bHighlighted = true;
+
+ return bHighlighted;
+}
+
+
+void VCLXAccessibleMenuItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ OAccessibleMenuItemComponent::FillAccessibleStateSet( rStateSet );
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsFocused() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ if ( IsSelected() )
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+
+ if ( IsChecked() )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleMenuItem::implGetText()
+{
+ return m_sItemText;
+}
+
+
+Locale VCLXAccessibleMenuItem::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleMenuItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleMenuItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenuItem";
+}
+
+
+Sequence< OUString > VCLXAccessibleMenuItem::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenuItem" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int16 VCLXAccessibleMenuItem::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+ // IA2 CWS. MT: We had the additional roles in UAA for ever, but never used them anywhere.
+ // Looks reasonable, but need to verify in Orca and VoiceOver.
+ sal_Int16 nRole = AccessibleRole::MENU_ITEM;
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ MenuItemBits nItemBits = m_pParent->GetItemBits(nItemId);
+ if( nItemBits & MenuItemBits::RADIOCHECK)
+ nRole = AccessibleRole::RADIO_MENU_ITEM;
+ else if( nItemBits & MenuItemBits::CHECKABLE)
+ nRole = AccessibleRole::CHECK_MENU_ITEM;
+ }
+ return nRole;
+}
+
+
+// XAccessibleText
+
+
+sal_Int32 VCLXAccessibleMenuItem::getCaretPosition()
+{
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::setCaretPosition( sal_Int32 nIndex )
+{
+
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+sal_Unicode VCLXAccessibleMenuItem::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ vcl::Font aFont = Application::GetSettings().GetStyleSettings().GetMenuFont();
+ sal_Int32 nBackColor = getBackground();
+ sal_Int32 nColor = getForeground();
+ return CharacterAttributesHelper( aFont, nBackColor, nColor )
+ .GetCharacterAttributes( aRequestedAttributes );
+}
+
+
+awt::Rectangle VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
+ tools::Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos );
+ tools::Rectangle aCharRect = m_pParent->GetCharacterBounds( nItemId, nIndex );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getCharacterCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_sItemText.getLength();
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pParent )
+ {
+ sal_uInt16 nItemId = 0;
+ tools::Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ sal_Int32 nI = m_pParent->GetIndexForPoint( aPnt, nItemId );
+ if ( nI != -1 && m_pParent->GetItemId( m_nItemPos ) == nItemId )
+ nIndex = nI;
+ }
+
+ return nIndex;
+}
+
+
+OUString VCLXAccessibleMenuItem::getSelectedText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getSelectionStart()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+sal_Int32 VCLXAccessibleMenuItem::getSelectionEnd()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, m_sItemText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+OUString VCLXAccessibleMenuItem::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_sItemText;
+}
+
+
+OUString VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pParent )
+ {
+ vcl::Window* pWindow = m_pParent->GetWindow();
+ if ( pWindow )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( getTextRange( nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleMenuItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleMenuItem::getAccessibleActionCount( )
+{
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ Click();
+
+ return true;
+}
+
+
+OUString VCLXAccessibleMenuItem::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_SELECT;
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ if ( m_pParent )
+ {
+ // create auto mnemonics
+ if (!(m_pParent->GetMenuFlags() & MenuFlags::NoAutoMnemonics))
+ m_pParent->CreateAutoMnemonics();
+
+ // activation key
+ KeyEvent aKeyEvent = m_pParent->GetActivationKey( m_pParent->GetItemId( m_nItemPos ) );
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ Sequence< awt::KeyStroke > aSeq1
+ {
+ {
+ 0, // Modifiers
+ static_cast< sal_Int16 >(aKeyCode.GetCode()),
+ aKeyEvent.GetCharCode(),
+ static_cast< sal_Int16 >( aKeyCode.GetFunction())
+ }
+ };
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU_BAR )
+ aSeq1.getArray()[0].Modifiers |= awt::KeyModifier::MOD2;
+ }
+ pKeyBindingHelper->AddKeyBinding( aSeq1 );
+
+ // complete menu activation key sequence
+ Sequence< awt::KeyStroke > aSeq;
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+ if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU )
+ {
+ Reference< XAccessibleAction > xAction( xParentContext, UNO_QUERY );
+ if ( xAction.is() && xAction->getAccessibleActionCount() > 0 )
+ {
+ Reference< XAccessibleKeyBinding > xKeyB( xAction->getAccessibleActionKeyBinding( 0 ) );
+ if ( xKeyB.is() && xKeyB->getAccessibleKeyBindingCount() > 1 )
+ aSeq = xKeyB->getAccessibleKeyBinding( 1 );
+ }
+ }
+ }
+ Sequence< awt::KeyStroke > aSeq2 = ::comphelper::concatSequences( aSeq, aSeq1 );
+ pKeyBindingHelper->AddKeyBinding( aSeq2 );
+
+ // accelerator key
+ vcl::KeyCode aAccelKeyCode = m_pParent->GetAccelKey( m_pParent->GetItemId( m_nItemPos ) );
+ if ( aAccelKeyCode.GetCode() != 0 )
+ {
+ Sequence< awt::KeyStroke > aSeq3
+ {
+ {
+ 0, // Modifiers
+ static_cast< sal_Int16 >(aAccelKeyCode.GetCode()),
+ aKeyEvent.GetCharCode(),
+ static_cast< sal_Int16 >(aAccelKeyCode.GetFunction())
+ }
+ };
+ if (aAccelKeyCode.GetModifier() != 0)
+ {
+ auto pSeq3 = aSeq3.getArray();
+ if ( aAccelKeyCode.IsShift() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aAccelKeyCode.IsMod1() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::MOD1;
+ if ( aAccelKeyCode.IsMod2() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::MOD2;
+ if ( aAccelKeyCode.IsMod3() )
+ pSeq3[0].Modifiers |= awt::KeyModifier::MOD3;
+ }
+ pKeyBindingHelper->AddKeyBinding( aSeq3 );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleMenuItem::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ if ( IsSelected() )
+ aValue <<= sal_Int32(1);
+ else
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleMenuItem::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue <= 0 )
+ {
+ DeSelect();
+ bReturn = true;
+ }
+ else if ( nValue >= 1 )
+ {
+ Select();
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleMenuItem::getMaximumValue( )
+{
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleMenuItem::getMinimumValue( )
+{
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleMenuItem::getMinimumIncrement( )
+{
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblemenuseparator.cxx b/accessibility/source/standard/vclxaccessiblemenuseparator.cxx
new file mode 100644
index 000000000..50a70df01
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblemenuseparator.cxx
@@ -0,0 +1,50 @@
+/* -*- 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 <standard/vclxaccessiblemenuseparator.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+VCLXAccessibleMenuSeparator::VCLXAccessibleMenuSeparator(Menu* pParent, sal_uInt16 nItemPos)
+ : OAccessibleMenuItemComponent(pParent, nItemPos, nullptr)
+{
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleMenuSeparator::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleMenuSeparator";
+}
+
+Sequence<OUString> VCLXAccessibleMenuSeparator::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleMenuSeparator" };
+}
+
+// XAccessibleContext
+
+sal_Int16 VCLXAccessibleMenuSeparator::getAccessibleRole() { return AccessibleRole::SEPARATOR; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblepopupmenu.cxx b/accessibility/source/standard/vclxaccessiblepopupmenu.cxx
new file mode 100644
index 000000000..ad3e7441e
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblepopupmenu.cxx
@@ -0,0 +1,84 @@
+/* -*- 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 <standard/vclxaccessiblepopupmenu.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::comphelper;
+
+
+
+
+bool VCLXAccessiblePopupMenu::IsFocused()
+{
+ return !IsChildHighlighted();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessiblePopupMenu::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessiblePopupMenu";
+}
+
+
+Sequence< OUString > VCLXAccessiblePopupMenu::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessiblePopupMenu" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessiblePopupMenu::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+sal_Int16 VCLXAccessiblePopupMenu::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::POPUP_MENU;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+sal_Int32 VCLXAccessiblePopupMenu::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return sal_Int32(Application::GetSettings().GetStyleSettings().GetMenuColor());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibleradiobutton.cxx b/accessibility/source/standard/vclxaccessibleradiobutton.cxx
new file mode 100644
index 000000000..c1a23ede2
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibleradiobutton.cxx
@@ -0,0 +1,281 @@
+/* -*- 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 <standard/vclxaccessibleradiobutton.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <comphelper/accessiblekeybindinghelper.hxx>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/window.hxx>
+#include <vcl/toolkit/button.hxx>
+#include <vcl/event.hxx>
+#include <vcl/vclevent.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleRadioButton
+
+
+void VCLXAccessibleRadioButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::RadiobuttonToggle:
+ {
+ Any aOldValue;
+ Any aNewValue;
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton && pVCLXRadioButton->getState() )
+ aNewValue <<= AccessibleStateType::CHECKED;
+ else
+ aOldValue <<= AccessibleStateType::CHECKED;
+
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ default:
+ VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleRadioButton::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleRelationSet( rRelationSet );
+
+ VclPtr< RadioButton > pRadioButton = GetAsDynamic< RadioButton >();
+ if ( !pRadioButton )
+ return;
+
+ std::vector< VclPtr<RadioButton> > aGroup(pRadioButton->GetRadioButtonGroup());
+ if (!aGroup.empty())
+ {
+ std::vector< Reference< XInterface > > aVec;
+ aVec.reserve(aGroup.size());
+ std::transform(aGroup.begin(), aGroup.end(), std::back_inserter(aVec),
+ [](const VclPtr<RadioButton>& rxItem) { return rxItem->GetAccessible(); });
+ rRelationSet.AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF,
+ comphelper::containerToSequence(aVec) ) );
+ }
+}
+
+
+void VCLXAccessibleRadioButton::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( pVCLXRadioButton->getState() )
+ rStateSet.AddState( AccessibleStateType::CHECKED );
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleRadioButton, VCLXAccessibleTextComponent, VCLXAccessibleRadioButton_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleRadioButton, VCLXAccessibleTextComponent, VCLXAccessibleRadioButton_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleRadioButton::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleRadioButton";
+}
+
+
+Sequence< OUString > VCLXAccessibleRadioButton::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleRadioButton" };
+}
+
+
+// XAccessibleAction
+
+
+sal_Int32 VCLXAccessibleRadioButton::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+sal_Bool VCLXAccessibleRadioButton::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton && !pVCLXRadioButton->getState() )
+ pVCLXRadioButton->setState( true );
+
+ return true;
+}
+
+OUString VCLXAccessibleRadioButton::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_SELECT;
+}
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleRadioButton::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ KeyEvent aKeyEvent = pWindow->GetActivationKey();
+ vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
+ if ( aKeyCode.GetCode() != 0 )
+ {
+ awt::KeyStroke aKeyStroke;
+ aKeyStroke.Modifiers = 0;
+ if ( aKeyCode.IsShift() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( aKeyCode.IsMod1() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
+ if ( aKeyCode.IsMod2() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
+ if ( aKeyCode.IsMod3() )
+ aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
+ aKeyStroke.KeyCode = aKeyCode.GetCode();
+ aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
+ aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
+ pKeyBindingHelper->AddKeyBinding( aKeyStroke );
+ }
+ }
+
+ return pKeyBindingHelper;
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleRadioButton::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton )
+ aValue <<= static_cast<sal_Int32>(pVCLXRadioButton->getState());
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleRadioButton::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
+ if ( pVCLXRadioButton )
+ {
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue < 0 )
+ nValue = 0;
+ else if ( nValue > 1 )
+ nValue = 1;
+
+ pVCLXRadioButton->setState( nValue == 1 );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleRadioButton::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleRadioButton::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleRadioButton::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(1);
+
+ return aValue;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblescrollbar.cxx b/accessibility/source/standard/vclxaccessiblescrollbar.cxx
new file mode 100644
index 000000000..9ddb5e12a
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblescrollbar.cxx
@@ -0,0 +1,272 @@
+/* -*- 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 <standard/vclxaccessiblescrollbar.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/scrbar.hxx>
+#include <vcl/vclevent.hxx>
+#include <strings.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+// VCLXAccessibleScrollBar
+
+
+void VCLXAccessibleScrollBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ScrollbarScroll:
+ {
+ NotifyAccessibleEvent( AccessibleEventId::VALUE_CHANGED, Any(), Any() );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleScrollBar::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ {
+ // IA2 CWS: scroll bar should not have FOCUSABLE state.
+ // rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::HORIZONTAL )
+ rStateSet.AddState( AccessibleStateType::HORIZONTAL );
+ else if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::VERTICAL )
+ rStateSet.AddState( AccessibleStateType::VERTICAL );
+ }
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleScrollBar, VCLXAccessibleComponent, VCLXAccessibleScrollBar_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleScrollBar, VCLXAccessibleComponent, VCLXAccessibleScrollBar_BASE )
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleScrollBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleScrollBar";
+}
+
+
+Sequence< OUString > VCLXAccessibleScrollBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleScrollBar" };
+}
+
+
+// XAccessibleAction
+
+constexpr sal_Int32 ACCESSIBLE_ACTION_COUNT=4;
+
+sal_Int32 VCLXAccessibleScrollBar::getAccessibleActionCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return ACCESSIBLE_ACTION_COUNT;
+}
+
+
+sal_Bool VCLXAccessibleScrollBar::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= ACCESSIBLE_ACTION_COUNT )
+ throw IndexOutOfBoundsException();
+
+ bool bReturn = false;
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ {
+ ScrollType eScrollType;
+ switch ( nIndex )
+ {
+ case 0: eScrollType = ScrollType::LineUp; break;
+ case 1: eScrollType = ScrollType::LineDown; break;
+ case 2: eScrollType = ScrollType::PageUp; break;
+ case 3: eScrollType = ScrollType::PageDown; break;
+ default: eScrollType = ScrollType::DontKnow; break;
+ }
+ if ( pScrollBar->DoScrollAction( eScrollType ) )
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+OUString VCLXAccessibleScrollBar::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= ACCESSIBLE_ACTION_COUNT )
+ throw IndexOutOfBoundsException();
+
+ OUString sDescription;
+
+ switch ( nIndex )
+ {
+ case 0: sDescription = OUString(RID_STR_ACC_ACTION_DECLINE); break;
+ case 1: sDescription = OUString(RID_STR_ACC_ACTION_INCLINE); break;
+ case 2: sDescription = OUString(RID_STR_ACC_ACTION_DECBLOCK); break;
+ case 3: sDescription = OUString(RID_STR_ACC_ACTION_INCBLOCK); break;
+ default: break;
+ }
+
+ return sDescription;
+}
+
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleScrollBar::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex < 0 || nIndex >= ACCESSIBLE_ACTION_COUNT )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessibleKeyBinding >();
+}
+
+
+// XAccessibleValue
+
+
+Any VCLXAccessibleScrollBar::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ aValue <<= pVCLXScrollBar->getValue();
+
+ return aValue;
+}
+
+
+sal_Bool VCLXAccessibleScrollBar::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ {
+ sal_Int32 nValue = 0, nValueMin = 0, nValueMax = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+ OSL_VERIFY( getMinimumValue() >>= nValueMin );
+ OSL_VERIFY( getMaximumValue() >>= nValueMax );
+
+ if ( nValue < nValueMin )
+ nValue = nValueMin;
+ else if ( nValue > nValueMax )
+ nValue = nValueMax;
+
+ pVCLXScrollBar->setValue( nValue );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+
+Any VCLXAccessibleScrollBar::getMaximumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ aValue <<= pVCLXScrollBar->getMaximum();
+
+ return aValue;
+}
+
+
+Any VCLXAccessibleScrollBar::getMinimumValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ aValue <<= sal_Int32(0);
+
+ return aValue;
+}
+
+Any VCLXAccessibleScrollBar::getMinimumIncrement( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Any();
+}
+
+
+OUString VCLXAccessibleScrollBar::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString aName;
+ VCLXScrollBar* pVCLXScrollBar = static_cast< VCLXScrollBar* >( GetVCLXWindow() );
+ if ( pVCLXScrollBar )
+ {
+ if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::HORIZONTAL )
+ aName = AccResId( RID_STR_ACC_SCROLLBAR_NAME_HORIZONTAL );
+ else if ( pVCLXScrollBar->getOrientation() == ScrollBarOrientation::VERTICAL )
+ aName = AccResId( RID_STR_ACC_SCROLLBAR_NAME_VERTICAL );
+ }
+ return aName;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblestatusbar.cxx b/accessibility/source/standard/vclxaccessiblestatusbar.cxx
new file mode 100644
index 000000000..d6e3e0ef5
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblestatusbar.cxx
@@ -0,0 +1,335 @@
+/* -*- 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 <standard/vclxaccessiblestatusbar.hxx>
+#include <standard/vclxaccessiblestatusbaritem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/status.hxx>
+#include <vcl/vclevent.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleStatusBar::VCLXAccessibleStatusBar( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ m_pStatusBar = GetAs<StatusBar>();
+
+ if ( m_pStatusBar )
+ m_aAccessibleChildren.assign( m_pStatusBar->GetItemCount(), Reference< XAccessible >() );
+}
+
+
+void VCLXAccessibleStatusBar::UpdateShowing( sal_Int32 i, bool bShowing )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem )
+ pVCLXAccessibleStatusBarItem->SetShowing( bShowing );
+ }
+ }
+}
+
+
+void VCLXAccessibleStatusBar::UpdateItemName( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem )
+ {
+ OUString sItemName = pVCLXAccessibleStatusBarItem->GetItemName();
+ pVCLXAccessibleStatusBarItem->SetItemName( sItemName );
+ }
+ }
+}
+
+
+void VCLXAccessibleStatusBar::UpdateItemText( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem )
+ {
+ OUString sItemText = pVCLXAccessibleStatusBarItem->GetItemText();
+ pVCLXAccessibleStatusBarItem->SetItemText( sItemText );
+ }
+ }
+}
+
+
+void VCLXAccessibleStatusBar::InsertChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ return;
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // send accessible child event
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleStatusBar::RemoveChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // get the accessible of the removed page
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+}
+
+
+void VCLXAccessibleStatusBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::StatusbarItemAdded:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ InsertChild( nItemPos );
+ }
+ }
+ break;
+ case VclEventId::StatusbarItemRemoved:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleStatusBarItem* pVCLXAccessibleStatusBarItem = static_cast< VCLXAccessibleStatusBarItem* >( xChild.get() );
+ if ( pVCLXAccessibleStatusBarItem && pVCLXAccessibleStatusBarItem->GetItemId() == nItemId )
+ {
+ RemoveChild( i );
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VclEventId::StatusbarAllItemsRemoved:
+ {
+ for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
+ RemoveChild( i );
+ }
+ break;
+ case VclEventId::StatusbarShowItem:
+ case VclEventId::StatusbarHideItem:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ UpdateShowing( nItemPos, rVclWindowEvent.GetId() == VclEventId::StatusbarShowItem );
+ }
+ }
+ break;
+ case VclEventId::StatusbarNameChanged:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ UpdateItemName( nItemPos );
+ }
+ }
+ break;
+ case VclEventId::StatusbarDrawItem:
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ UpdateItemText( nItemPos );
+ }
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pStatusBar )
+ {
+ m_pStatusBar = nullptr;
+
+ // dispose all children
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleStatusBar::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ if ( !m_pStatusBar )
+ return;
+
+ m_pStatusBar = nullptr;
+
+ // dispose all children
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleStatusBar::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleStatusBar";
+}
+
+
+Sequence< OUString > VCLXAccessibleStatusBar::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleStatusBar" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleStatusBar::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_aAccessibleChildren.size();
+}
+
+
+Reference< XAccessible > VCLXAccessibleStatusBar::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = m_pStatusBar->GetItemId( static_cast<sal_uInt16>(i) );
+
+ xChild = new VCLXAccessibleStatusBarItem( m_pStatusBar, nItemId );
+
+ // insert into status bar item list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleStatusBar::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xChild;
+ if ( m_pStatusBar )
+ {
+ sal_uInt16 nItemId = m_pStatusBar->GetItemId( VCLPoint( rPoint ) );
+ sal_Int32 nItemPos = m_pStatusBar->GetItemPos( nItemId );
+ if ( nItemPos >= 0 && o3tl::make_unsigned(nItemPos) < m_aAccessibleChildren.size() )
+ xChild = getAccessibleChild( nItemPos );
+ }
+
+ return xChild;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessiblestatusbaritem.cxx b/accessibility/source/standard/vclxaccessiblestatusbaritem.cxx
new file mode 100644
index 000000000..840674206
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessiblestatusbaritem.cxx
@@ -0,0 +1,587 @@
+/* -*- 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 <standard/vclxaccessiblestatusbaritem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/status.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleStatusBarItem::VCLXAccessibleStatusBarItem( StatusBar* pStatusBar, sal_uInt16 nItemId )
+ :m_pStatusBar( pStatusBar )
+ ,m_nItemId( nItemId )
+{
+
+ m_sItemName = GetItemName();
+ m_sItemText = GetItemText();
+ m_bShowing = IsShowing();
+}
+
+
+bool VCLXAccessibleStatusBarItem::IsShowing()
+{
+ bool bShowing = false;
+
+ if ( m_pStatusBar )
+ bShowing = m_pStatusBar->IsItemVisible( m_nItemId );
+
+ return bShowing;
+}
+
+
+void VCLXAccessibleStatusBarItem::SetShowing( bool bShowing )
+{
+ if ( m_bShowing != bShowing )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bShowing )
+ aOldValue <<= AccessibleStateType::SHOWING;
+ else
+ aNewValue <<= AccessibleStateType::SHOWING;
+ m_bShowing = bShowing;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleStatusBarItem::SetItemName( const OUString& sItemName )
+{
+ if ( m_sItemName != sItemName )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sItemName;
+ aNewValue <<= sItemName;
+ m_sItemName = sItemName;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString VCLXAccessibleStatusBarItem::GetItemName()
+{
+ OUString sName;
+ if ( m_pStatusBar )
+ sName = m_pStatusBar->GetAccessibleName( m_nItemId );
+
+ return sName;
+}
+
+
+void VCLXAccessibleStatusBarItem::SetItemText( const OUString& sItemText )
+{
+ Any aOldValue, aNewValue;
+ if ( implInitTextChangedEvent( m_sItemText, sItemText, aOldValue, aNewValue ) )
+ {
+ m_sItemText = sItemText;
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString VCLXAccessibleStatusBarItem::GetItemText()
+{
+ OUString sText;
+ if ( m_pStatusBar )
+ sText = m_pStatusBar->GetItemText( m_nItemId );
+
+ return sText;
+}
+
+
+void VCLXAccessibleStatusBarItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ if ( IsShowing() )
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle VCLXAccessibleStatusBarItem::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pStatusBar )
+ aBounds = AWTRectangle( m_pStatusBar->GetItemRect( m_nItemId ) );
+
+ return aBounds;
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleStatusBarItem::implGetText()
+{
+ return GetItemText();
+}
+
+
+lang::Locale VCLXAccessibleStatusBarItem::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleStatusBarItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleStatusBarItem, AccessibleTextHelper_BASE, VCLXAccessibleStatusBarItem_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleStatusBarItem, AccessibleTextHelper_BASE, VCLXAccessibleStatusBarItem_BASE )
+
+
+// XComponent
+
+
+void VCLXAccessibleStatusBarItem::disposing()
+{
+ AccessibleTextHelper_BASE::disposing();
+
+ m_pStatusBar = nullptr;
+ m_sItemName.clear();
+ m_sItemText.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleStatusBarItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleStatusBarItem";
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+
+Sequence< OUString > VCLXAccessibleStatusBarItem::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleStatusBarItem" };
+}
+
+
+// XAccessible
+
+
+Reference< XAccessibleContext > VCLXAccessibleStatusBarItem::getAccessibleContext( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+Reference< XAccessible > VCLXAccessibleStatusBarItem::getAccessibleChild( sal_Int32 )
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+Reference< XAccessible > VCLXAccessibleStatusBarItem::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pStatusBar )
+ xParent = m_pStatusBar->GetAccessible();
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+ if ( m_pStatusBar )
+ nIndexInParent = m_pStatusBar->GetItemPos( m_nItemId );
+
+ return nIndexInParent;
+}
+
+
+sal_Int16 VCLXAccessibleStatusBarItem::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::LABEL;
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pStatusBar )
+ sDescription = m_pStatusBar->GetHelpText( m_nItemId );
+
+ return sDescription;
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemName();
+}
+
+
+Reference< XAccessibleRelationSet > VCLXAccessibleStatusBarItem::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Reference< XAccessibleStateSet > VCLXAccessibleStatusBarItem::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+Locale VCLXAccessibleStatusBarItem::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleStatusBarItem::getAccessibleAtPoint( const awt::Point& )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Reference< XAccessible >();
+}
+
+
+void VCLXAccessibleStatusBarItem::grabFocus( )
+{
+ // no focus for status bar items
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > VCLXAccessibleStatusBarItem::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemText();
+}
+
+
+OUString VCLXAccessibleStatusBarItem::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleText
+
+OUString VCLXAccessibleStatusBarItem::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemText();
+}
+
+OUString VCLXAccessibleStatusBarItem::getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex)
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange(GetItemText(), nStartIndex, nEndIndex);
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getCharacterCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetItemText().getLength();
+}
+
+sal_Unicode VCLXAccessibleStatusBarItem::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( GetItemText(), nIndex );
+}
+
+sal_Int32 VCLXAccessibleStatusBarItem::getCaretPosition()
+{
+ OExternalLockGuard aGuard( this );
+
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::setCaretPosition( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, GetItemText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleStatusBarItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ Sequence< PropertyValue > aValues;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pStatusBar )
+ {
+ vcl::Font aFont = m_pStatusBar->GetFont();
+ sal_Int32 nBackColor = getBackground();
+ sal_Int32 nColor = getForeground();
+ aValues = CharacterAttributesHelper( aFont, nBackColor, nColor )
+ .GetCharacterAttributes( aRequestedAttributes );
+ }
+
+ return aValues;
+}
+
+
+awt::Rectangle VCLXAccessibleStatusBarItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pStatusBar )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = m_pStatusBar->GetItemRect( m_nItemId );
+ m_pStatusBar->RecordLayoutData( &aLayoutData, aItemRect );
+ tools::Rectangle aCharRect = aLayoutData.GetCharacterBounds( nIndex );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleStatusBarItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pStatusBar )
+ {
+ vcl::ControlLayoutData aLayoutData;
+ tools::Rectangle aItemRect = m_pStatusBar->GetItemRect( m_nItemId );
+ m_pStatusBar->RecordLayoutData( &aLayoutData, aItemRect );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ nIndex = aLayoutData.GetIndexForPoint( aPnt );
+ }
+
+ return nIndex;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pStatusBar )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pStatusBar->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( implGetTextRange( GetItemText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+
+sal_Bool VCLXAccessibleStatusBarItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletabcontrol.cxx b/accessibility/source/standard/vclxaccessibletabcontrol.cxx
new file mode 100644
index 000000000..c1ede9741
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletabcontrol.cxx
@@ -0,0 +1,488 @@
+/* -*- 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 <standard/vclxaccessibletabcontrol.hxx>
+#include <standard/vclxaccessibletabpage.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <o3tl/safeint.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/vclevent.hxx>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTabControl::VCLXAccessibleTabControl( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ m_pTabControl = GetAs<TabControl>();
+ if (!m_pTabControl)
+ return;
+ if (m_pTabControl->isDisposed())
+ {
+ m_pTabControl.clear();
+ return;
+ }
+ m_aAccessibleChildren.assign( m_pTabControl->GetPageCount(), Reference< XAccessible >() );
+}
+
+
+void VCLXAccessibleTabControl::UpdateFocused()
+{
+ for (const Reference<XAccessible>& xChild : m_aAccessibleChildren)
+ {
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->SetFocused( pVCLXAccessibleTabPage->IsFocused() );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::UpdateSelected( sal_Int32 i, bool bSelected )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->SetSelected( bSelected );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::UpdatePageText( sal_Int32 i )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->SetPageText( pVCLXAccessibleTabPage->GetPageText() );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::UpdateTabPage( sal_Int32 i, bool bNew )
+{
+ if ( i >= 0 && o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
+ {
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage )
+ pVCLXAccessibleTabPage->Update( bNew );
+ }
+ }
+}
+
+
+void VCLXAccessibleTabControl::InsertChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) > m_aAccessibleChildren.size() )
+ return;
+
+ // insert entry in child list
+ m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
+
+ // send accessible child event
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabControl::RemoveChild( sal_Int32 i )
+{
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ return;
+
+ // get the accessible of the removed page
+ Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
+
+ // remove entry in child list
+ m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
+
+ // send accessible child event
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ Reference< XComponent > xComponent( xChild, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+}
+
+
+void VCLXAccessibleTabControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::TabpageActivate:
+ case VclEventId::TabpageDeactivate:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
+ UpdateFocused();
+ UpdateSelected( nPagePos, rVclWindowEvent.GetId() == VclEventId::TabpageActivate );
+ }
+ }
+ break;
+ case VclEventId::TabpagePageTextChanged:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
+ UpdatePageText( nPagePos );
+ }
+ }
+ break;
+ case VclEventId::TabpageInserted:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
+ InsertChild( nPagePos );
+ }
+ }
+ break;
+ case VclEventId::TabpageRemoved:
+ {
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = static_cast<sal_uInt16>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xChild( getAccessibleChild( i ) );
+ if ( xChild.is() )
+ {
+ VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
+ if ( pVCLXAccessibleTabPage && pVCLXAccessibleTabPage->GetPageId() == nPageId )
+ {
+ RemoveChild( i );
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case VclEventId::TabpageRemovedAll:
+ {
+ for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
+ RemoveChild( i );
+ }
+ break;
+ case VclEventId::WindowGetFocus:
+ case VclEventId::WindowLoseFocus:
+ {
+ UpdateFocused();
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ if ( m_pTabControl )
+ {
+ m_pTabControl = nullptr;
+
+ // dispose all tab pages
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+ }
+
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleTabControl::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow:
+ case VclEventId::WindowHide:
+ {
+ if ( m_pTabControl )
+ {
+ vcl::Window* pChild = static_cast< vcl::Window* >( rVclWindowEvent.GetData() );
+ if ( pChild && pChild->GetType() == WindowType::TABPAGE )
+ {
+ for ( sal_Int32 i = 0, nCount = m_pTabControl->GetPageCount(); i < nCount; ++i )
+ {
+ sal_uInt16 nPageId = m_pTabControl->GetPageId( static_cast<sal_uInt16>(i) );
+ TabPage* pTabPage = m_pTabControl->GetTabPage( nPageId );
+ if ( pTabPage == static_cast<TabPage*>(pChild) )
+ UpdateTabPage( i, rVclWindowEvent.GetId() == VclEventId::WindowShow );
+ }
+ }
+ }
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
+ }
+}
+
+
+void VCLXAccessibleTabControl::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+
+ if ( m_pTabControl )
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE )
+
+
+// XComponent
+
+
+void VCLXAccessibleTabControl::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ if ( !m_pTabControl )
+ return;
+
+ m_pTabControl = nullptr;
+
+ // dispose all tab pages
+ for (const Reference<XAccessible>& i : m_aAccessibleChildren)
+ {
+ Reference< XComponent > xComponent( i, UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ m_aAccessibleChildren.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleTabControl::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleTabControl";
+}
+
+
+Sequence< OUString > VCLXAccessibleTabControl::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleTabControl" };
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleTabControl::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return m_aAccessibleChildren.size();
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabControl::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ return implGetAccessibleChild( i );
+}
+
+Reference< XAccessible > VCLXAccessibleTabControl::implGetAccessibleChild( sal_Int32 i )
+{
+ Reference< XAccessible > xChild = m_aAccessibleChildren[i];
+ if ( !xChild.is() )
+ {
+ sal_uInt16 nPageId = m_pTabControl ? m_pTabControl->GetPageId(static_cast<sal_uInt16>(i)) : 0;
+ if (nPageId)
+ {
+ xChild = new VCLXAccessibleTabPage( m_pTabControl, nPageId );
+
+ // insert into tab page list
+ m_aAccessibleChildren[i] = xChild;
+ }
+ }
+
+ return xChild;
+}
+
+
+sal_Int16 VCLXAccessibleTabControl::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::PAGE_TAB_LIST;
+}
+
+
+OUString VCLXAccessibleTabControl::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleSelection
+
+
+void VCLXAccessibleTabControl::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pTabControl )
+ m_pTabControl->SelectTabPage( m_pTabControl->GetPageId( static_cast<sal_uInt16>(nChildIndex) ) );
+}
+
+
+sal_Bool VCLXAccessibleTabControl::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ return implIsAccessibleChildSelected( nChildIndex );
+}
+
+bool VCLXAccessibleTabControl::implIsAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ bool bSelected = false;
+ if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_pTabControl->GetPageId( static_cast<sal_uInt16>(nChildIndex) ) )
+ bSelected = true;
+
+ return bSelected;
+}
+
+
+void VCLXAccessibleTabControl::clearAccessibleSelection( )
+{
+ // This method makes no sense in a tab control, and so does nothing.
+}
+
+
+void VCLXAccessibleTabControl::selectAllAccessibleChildren( )
+{
+ selectAccessibleChild( 0 );
+}
+
+
+sal_Int32 VCLXAccessibleTabControl::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 1;
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabControl::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nSelectedChildIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+
+ for ( std::size_t i = 0, nCount = m_aAccessibleChildren.size(); i < nCount; i++ )
+ {
+ if ( implIsAccessibleChildSelected( i ) )
+ {
+ xChild = implGetAccessibleChild( i );
+ break;
+ }
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleTabControl::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= m_aAccessibleChildren.size() )
+ throw IndexOutOfBoundsException();
+
+ // This method makes no sense in a tab control, and so does nothing.
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletabpage.cxx b/accessibility/source/standard/vclxaccessibletabpage.cxx
new file mode 100644
index 000000000..8dd5a2419
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletabpage.cxx
@@ -0,0 +1,675 @@
+/* -*- 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 <standard/vclxaccessibletabpage.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTabPage::VCLXAccessibleTabPage( TabControl* pTabControl, sal_uInt16 nPageId )
+ :m_pTabControl( pTabControl )
+ ,m_nPageId( nPageId )
+{
+ m_bFocused = IsFocused();
+ m_bSelected = IsSelected();
+ m_sPageText = GetPageText();
+}
+
+
+VCLXAccessibleTabPage::~VCLXAccessibleTabPage()
+{
+}
+
+
+bool VCLXAccessibleTabPage::IsFocused() const
+{
+ bool bFocused = false;
+
+ if ( m_pTabControl && m_pTabControl->HasFocus() && m_pTabControl->GetCurPageId() == m_nPageId )
+ bFocused = true;
+
+ return bFocused;
+}
+
+
+bool VCLXAccessibleTabPage::IsSelected() const
+{
+ bool bSelected = false;
+
+ if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_nPageId )
+ bSelected = true;
+
+ return bSelected;
+}
+
+
+void VCLXAccessibleTabPage::SetFocused( bool bFocused )
+{
+ if ( m_bFocused != bFocused )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bFocused )
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ else
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ m_bFocused = bFocused;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabPage::SetSelected( bool bSelected )
+{
+ if ( m_bSelected != bSelected )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bSelected )
+ aOldValue <<= AccessibleStateType::SELECTED;
+ else
+ aNewValue <<= AccessibleStateType::SELECTED;
+ m_bSelected = bSelected;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabPage::SetPageText( const OUString& sPageText )
+{
+ Any aOldValue, aNewValue;
+ if ( OCommonAccessibleText::implInitTextChangedEvent( m_sPageText, sPageText, aOldValue, aNewValue ) )
+ {
+ Any aOldName, aNewName;
+ aOldName <<= m_sPageText;
+ aNewName <<= sPageText;
+ m_sPageText = sPageText;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldName, aNewName );
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+OUString VCLXAccessibleTabPage::GetPageText()
+{
+ OUString sText;
+ if ( m_pTabControl )
+ sText = OutputDevice::GetNonMnemonicString( m_pTabControl->GetPageText( m_nPageId ) );
+
+ return sText;
+}
+
+
+void VCLXAccessibleTabPage::Update( bool bNew )
+{
+ if ( !m_pTabControl )
+ return;
+
+ TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
+ if ( !pTabPage )
+ return;
+
+ Reference< XAccessible > xChild( pTabPage->GetAccessible( bNew ) );
+ if ( xChild.is() )
+ {
+ Any aOldValue, aNewValue;
+ if ( bNew )
+ aNewValue <<= xChild;
+ else
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTabPage::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ rStateSet.AddState( AccessibleStateType::ENABLED );
+ rStateSet.AddState( AccessibleStateType::SENSITIVE );
+
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+
+ if ( IsFocused() )
+ rStateSet.AddState( AccessibleStateType::FOCUSED );
+
+ rStateSet.AddState( AccessibleStateType::VISIBLE );
+
+ rStateSet.AddState( AccessibleStateType::SHOWING );
+
+ rStateSet.AddState( AccessibleStateType::SELECTABLE );
+
+ if ( IsSelected() )
+ rStateSet.AddState( AccessibleStateType::SELECTED );
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle VCLXAccessibleTabPage::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pTabControl )
+ aBounds = AWTRectangle( m_pTabControl->GetTabBounds( m_nPageId ) );
+
+ return aBounds;
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleTabPage::implGetText()
+{
+ return GetPageText();
+}
+
+
+lang::Locale VCLXAccessibleTabPage::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleTabPage::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTabPage, AccessibleTextHelper_BASE, VCLXAccessibleTabPage_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTabPage, AccessibleTextHelper_BASE, VCLXAccessibleTabPage_BASE )
+
+
+// XComponent
+
+
+void VCLXAccessibleTabPage::disposing()
+{
+ AccessibleTextHelper_BASE::disposing();
+
+ m_pTabControl = nullptr;
+ m_sPageText.clear();
+}
+
+
+// XServiceInfo
+
+
+OUString VCLXAccessibleTabPage::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleTabPage";
+}
+
+
+sal_Bool VCLXAccessibleTabPage::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+
+Sequence< OUString > VCLXAccessibleTabPage::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AccessibleTabPage" };
+}
+
+
+// XAccessible
+
+
+Reference< XAccessibleContext > VCLXAccessibleTabPage::getAccessibleContext( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return this;
+}
+
+
+// XAccessibleContext
+
+
+sal_Int32 VCLXAccessibleTabPage::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+ return implGetAccessibleChildCount();
+}
+
+sal_Int32 VCLXAccessibleTabPage::implGetAccessibleChildCount()
+{
+ sal_Int32 nCount = 0;
+ if ( m_pTabControl )
+ {
+ TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
+ if ( pTabPage && pTabPage->IsVisible() )
+ nCount = 1;
+ }
+
+ return nCount;
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleChild( sal_Int32 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i < 0 || i >= implGetAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ if ( m_pTabControl )
+ {
+ TabPage* pTabPage = m_pTabControl->GetTabPage( m_nPageId );
+ if ( pTabPage && pTabPage->IsVisible() )
+ xChild = pTabPage->GetAccessible();
+ }
+
+ return xChild;
+}
+
+
+Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pTabControl )
+ xParent = m_pTabControl->GetAccessible();
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndexInParent = -1;
+ if ( m_pTabControl )
+ nIndexInParent = m_pTabControl->GetPagePos( m_nPageId );
+
+ return nIndexInParent;
+}
+
+sal_Int16 VCLXAccessibleTabPage::getAccessibleRole()
+{
+ OExternalLockGuard aGuard( this );
+
+ return AccessibleRole::PAGE_TAB;
+}
+
+OUString VCLXAccessibleTabPage::getAccessibleDescription()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sDescription;
+ if ( m_pTabControl )
+ sDescription = m_pTabControl->GetAccessibleDescription( m_nPageId );
+
+ return sDescription;
+}
+
+OUString VCLXAccessibleTabPage::getAccessibleName()
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sName;
+ if ( m_pTabControl )
+ sName = m_pTabControl->GetAccessibleName( m_nPageId );
+
+ return sName;
+}
+
+Reference< XAccessibleRelationSet > VCLXAccessibleTabPage::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+
+Reference< XAccessibleStateSet > VCLXAccessibleTabPage::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ FillAccessibleStateSet( *pStateSetHelper );
+ }
+ else
+ {
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+ }
+
+ return pStateSetHelper;
+}
+
+
+Locale VCLXAccessibleTabPage::getLocale( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+// XAccessibleComponent
+
+
+Reference< XAccessible > VCLXAccessibleTabPage::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xChild;
+ for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ Reference< XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+}
+
+
+void VCLXAccessibleTabPage::grabFocus( )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( m_pTabControl )
+ {
+ m_pTabControl->SelectTabPage( m_nPageId );
+ m_pTabControl->GrabFocus();
+ }
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getForeground();
+ }
+
+ return nColor;
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nColor = 0;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ nColor = xParentComp->getBackground();
+ }
+
+ return nColor;
+}
+
+
+// XAccessibleExtendedComponent
+
+
+Reference< awt::XFont > VCLXAccessibleTabPage::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< awt::XFont > xFont;
+ Reference< XAccessible > xParent = getAccessibleParent();
+ if ( xParent.is() )
+ {
+ Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
+ if ( xParentComp.is() )
+ xFont = xParentComp->getFont();
+ }
+
+ return xFont;
+}
+
+
+OUString VCLXAccessibleTabPage::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+OUString VCLXAccessibleTabPage::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OUString();
+}
+
+
+// XAccessibleText
+
+OUString VCLXAccessibleTabPage::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetPageText();
+}
+
+OUString VCLXAccessibleTabPage::getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex)
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange(GetPageText(), nStartIndex, nEndIndex);
+}
+
+sal_Unicode VCLXAccessibleTabPage::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( GetPageText(), nIndex );
+}
+
+sal_Int32 VCLXAccessibleTabPage::getCharacterCount()
+{
+ return GetPageText().getLength();
+}
+
+sal_Int32 VCLXAccessibleTabPage::getCaretPosition()
+{
+ OExternalLockGuard aGuard( this );
+
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleTabPage::setCaretPosition( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, GetPageText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleTabPage::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ Sequence< PropertyValue > aValues;
+ OUString sText( GetPageText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pTabControl )
+ {
+ vcl::Font aFont = m_pTabControl->GetFont();
+ sal_Int32 nBackColor = getBackground();
+ sal_Int32 nColor = getForeground();
+ aValues = CharacterAttributesHelper( aFont, nBackColor, nColor )
+ .GetCharacterAttributes( aRequestedAttributes );
+ }
+
+ return aValues;
+}
+
+
+awt::Rectangle VCLXAccessibleTabPage::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, GetPageText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pTabControl )
+ {
+ tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
+ tools::Rectangle aCharRect = m_pTabControl->GetCharacterBounds( m_nPageId, nIndex );
+ aCharRect.Move( -aPageRect.Left(), -aPageRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+
+sal_Int32 VCLXAccessibleTabPage::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pTabControl )
+ {
+ sal_uInt16 nPageId = 0;
+ tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aPageRect.TopLeft();
+ sal_Int32 nI = m_pTabControl->GetIndexForPoint( aPnt, nPageId );
+ if ( nI != -1 && m_nPageId == nPageId )
+ nIndex = nI;
+ }
+
+ return nIndex;
+}
+
+
+sal_Bool VCLXAccessibleTabPage::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, GetPageText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+sal_Bool VCLXAccessibleTabPage::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pTabControl )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pTabControl->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( implGetTextRange( GetPageText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleTabPage::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletabpagewindow.cxx b/accessibility/source/standard/vclxaccessibletabpagewindow.cxx
new file mode 100644
index 000000000..c8408d24b
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletabpagewindow.cxx
@@ -0,0 +1,133 @@
+/* -*- 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 <standard/vclxaccessibletabpagewindow.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTabPageWindow::VCLXAccessibleTabPageWindow( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ m_pTabPage = GetAs<TabPage>();
+ m_pTabControl = nullptr;
+ m_nPageId = 0;
+ if ( !m_pTabPage )
+ return;
+
+ vcl::Window* pParent = m_pTabPage->GetAccessibleParentWindow();
+ if ( !(pParent && pParent->GetType() == WindowType::TABCONTROL) )
+ return;
+
+ m_pTabControl = static_cast< TabControl* >( pParent );
+ if ( m_pTabControl )
+ {
+ for ( sal_uInt16 i = 0, nCount = m_pTabControl->GetPageCount(); i < nCount; ++i )
+ {
+ sal_uInt16 nPageId = m_pTabControl->GetPageId( i );
+ if ( m_pTabControl->GetTabPage( nPageId ) == m_pTabPage.get() )
+ m_nPageId = nPageId;
+ }
+ }
+}
+
+
+// OCommonAccessibleComponent
+
+
+awt::Rectangle VCLXAccessibleTabPageWindow::implGetBounds()
+{
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+
+ if ( m_pTabControl )
+ {
+ tools::Rectangle aPageRect = m_pTabControl->GetTabBounds( m_nPageId );
+ if ( m_pTabPage )
+ {
+ tools::Rectangle aRect( m_pTabPage->GetPosPixel(), m_pTabPage->GetSizePixel() );
+ aRect.Move( -aPageRect.Left(), -aPageRect.Top() );
+ aBounds = AWTRectangle( aRect );
+ }
+ }
+
+ return aBounds;
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleTabPageWindow::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ m_pTabControl = nullptr;
+ m_pTabPage = nullptr;
+}
+
+
+// XAccessibleContext
+
+
+Reference< XAccessible > VCLXAccessibleTabPageWindow::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xParent;
+ if ( m_pTabControl )
+ {
+ Reference< XAccessible > xAcc( m_pTabControl->GetAccessible() );
+ if ( xAcc.is() )
+ {
+ Reference< XAccessibleContext > xCont( xAcc->getAccessibleContext() );
+ if ( xCont.is() )
+ {
+ sal_uInt16 const nPagePos(m_pTabControl->GetPagePos(m_nPageId));
+ SAL_WARN_IF(nPagePos == TAB_PAGE_NOTFOUND, "accessibility",
+ "getAccessibleParent(): no tab page");
+ if (nPagePos != TAB_PAGE_NOTFOUND)
+ {
+ xParent = xCont->getAccessibleChild(nPagePos);
+ }
+ }
+ }
+ }
+
+ return xParent;
+}
+
+
+sal_Int32 VCLXAccessibleTabPageWindow::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ return 0;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletextcomponent.cxx b/accessibility/source/standard/vclxaccessibletextcomponent.cxx
new file mode 100644
index 000000000..c5dba0df9
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletextcomponent.cxx
@@ -0,0 +1,376 @@
+/* -*- 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 <standard/vclxaccessibletextcomponent.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/characterattributeshelper.hxx>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+using namespace ::comphelper;
+
+
+
+
+VCLXAccessibleTextComponent::VCLXAccessibleTextComponent( VCLXWindow* pVCLXWindow )
+ :VCLXAccessibleComponent( pVCLXWindow )
+{
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ m_sText = OutputDevice::GetNonMnemonicString( pWindow->GetText() );
+}
+
+
+void VCLXAccessibleTextComponent::SetText( const OUString& sText )
+{
+ Any aOldValue, aNewValue;
+ if ( implInitTextChangedEvent( m_sText, sText, aOldValue, aNewValue ) )
+ {
+ m_sText = sText;
+ NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+
+void VCLXAccessibleTextComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowFrameTitleChanged:
+ {
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ SetText( implGetText() );
+ }
+ break;
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+
+// OCommonAccessibleText
+
+
+OUString VCLXAccessibleTextComponent::implGetText()
+{
+ OUString aText;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ aText = OutputDevice::GetNonMnemonicString( pWindow->GetText() );
+
+ return aText;
+}
+
+
+lang::Locale VCLXAccessibleTextComponent::implGetLocale()
+{
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+
+void VCLXAccessibleTextComponent::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+
+// XComponent
+
+
+void VCLXAccessibleTextComponent::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ m_sText.clear();
+}
+
+
+// XInterface
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTextComponent, VCLXAccessibleComponent, VCLXAccessibleTextComponent_BASE )
+
+
+// XTypeProvider
+
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTextComponent, VCLXAccessibleComponent, VCLXAccessibleTextComponent_BASE )
+
+
+// XAccessibleText
+
+
+sal_Int32 VCLXAccessibleTextComponent::getCaretPosition()
+{
+ return -1;
+}
+
+
+sal_Bool VCLXAccessibleTextComponent::setCaretPosition( sal_Int32 nIndex )
+{
+ return setSelection( nIndex, nIndex );
+}
+
+
+sal_Unicode VCLXAccessibleTextComponent::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
+}
+
+
+Sequence< PropertyValue > VCLXAccessibleTextComponent::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
+{
+ OExternalLockGuard aGuard( this );
+
+ Sequence< PropertyValue > aValues;
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ vcl::Font aFont = pWindow->GetControlFont();
+
+ Color nBackColor = pWindow->GetControlBackground();
+ Color nColor = pWindow->GetControlForeground();
+
+ // MT: Code with default font was introduced with the IA2 CWS, but I am not convinced that this is the correct font...
+ // Decide what to do when we have a concrete issue.
+ /*
+ Font aDefaultVCLFont;
+ OutputDevice* pDev = Application::GetDefaultDevice();
+ if ( pDev )
+ {
+ aDefaultVCLFont = pDev->GetSettings().GetStyleSettings().GetAppFont();
+ if ( !aFont.GetName().Len() )
+ {
+ String aDefaultName = aDefaultVCLFont.GetName();
+ aFont.SetName( aDefaultName );
+ }
+ if ( !aFont.GetHeight() )
+ {
+ aFont.SetHeight( aDefaultVCLFont.GetHeight() );
+ }
+ if ( aFont.GetWeight() == WEIGHT_DONTKNOW )
+ {
+ aFont.SetWeight( aDefaultVCLFont.GetWeight() );
+ }
+
+ //if nColor is -1, it may indicate that the default color black is using.
+ if ( nColor == -1)
+ {
+ nColor = aDefaultVCLFont.GetColor().GetColor();
+ }
+ }
+ */
+
+ // MT: Adjustment stuff was introduced with the IA2 CWS, but adjustment is not a character attribute...
+ // In case we reintroduce it, use adjustment as extra parameter for the CharacterAttributesHelper...
+ /*
+ WinBits aBits = GetWindow()->GetStyle();
+ sal_Int16 nAdjust = -1;
+ if ( aBits & WB_LEFT )
+ {
+ nAdjust = style::ParagraphAdjust_LEFT;
+ }
+ else if ( aBits & WB_RIGHT )
+ {
+ nAdjust = style::ParagraphAdjust_RIGHT;
+ }
+ else if ( aBits & WB_CENTER )
+ {
+ nAdjust = style::ParagraphAdjust_CENTER;
+ }
+ */
+
+ aValues = CharacterAttributesHelper( aFont, sal_Int32(nBackColor), sal_Int32(nColor) )
+ .GetCharacterAttributes( aRequestedAttributes );
+ }
+
+ return aValues;
+}
+
+
+awt::Rectangle VCLXAccessibleTextComponent::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aRect;
+ VclPtr< Control > pControl = GetAs< Control >();
+ if ( pControl )
+ aRect = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
+
+ return aRect;
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getCharacterCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetText().getLength();
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ VclPtr< Control > pControl = GetAs< Control >();
+ if ( pControl )
+ nIndex = pControl->GetIndexForPoint( VCLPoint( aPoint ) );
+
+ return nIndex;
+}
+
+
+OUString VCLXAccessibleTextComponent::getSelectedText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getSelectedText();
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getSelectionStart()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getSelectionStart();
+}
+
+
+sal_Int32 VCLXAccessibleTextComponent::getSelectionEnd()
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getSelectionEnd();
+}
+
+
+sal_Bool VCLXAccessibleTextComponent::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+
+OUString VCLXAccessibleTextComponent::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return implGetText();
+}
+
+
+OUString VCLXAccessibleTextComponent::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleTextComponent::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleTextComponent::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
+}
+
+
+css::accessibility::TextSegment VCLXAccessibleTextComponent::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
+}
+
+
+sal_Bool VCLXAccessibleTextComponent::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleTextComponent::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletextfield.cxx b/accessibility/source/standard/vclxaccessibletextfield.cxx
new file mode 100644
index 000000000..c94e46e3d
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletextfield.cxx
@@ -0,0 +1,107 @@
+/* -*- 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 <standard/vclxaccessibletextfield.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::accessibility;
+
+
+VCLXAccessibleTextField::VCLXAccessibleTextField (VCLXWindow* pVCLWindow, const Reference< XAccessible >& _xParent) :
+ VCLXAccessibleTextComponent (pVCLWindow),
+ m_xParent( _xParent )
+
+{
+}
+
+
+OUString VCLXAccessibleTextField::implGetText()
+{
+ OUString aText;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if (pListBox && !pListBox->IsInDropDown())
+ aText = pListBox->GetSelectedEntry();
+
+ return aText;
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleTextField, VCLXAccessibleTextComponent, VCLXAccessible_BASE)
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleTextField, VCLXAccessibleTextComponent, VCLXAccessible_BASE)
+
+
+// XAccessible
+
+Reference<XAccessibleContext> SAL_CALL
+ VCLXAccessibleTextField::getAccessibleContext()
+{
+ return this;
+}
+
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleTextField::getAccessibleChildCount()
+{
+ return 0;
+}
+
+
+Reference<XAccessible> SAL_CALL VCLXAccessibleTextField::getAccessibleChild (sal_Int32)
+{
+ throw IndexOutOfBoundsException();
+}
+
+
+sal_Int16 SAL_CALL VCLXAccessibleTextField::getAccessibleRole()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return AccessibleRole::TEXT;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleTextField::getAccessibleParent( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return m_xParent;
+}
+
+
+// XServiceInfo
+
+OUString VCLXAccessibleTextField::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleTextField";
+}
+
+
+Sequence< OUString > VCLXAccessibleTextField::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleTextComponent::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleTextField"});
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletoolbox.cxx b/accessibility/source/standard/vclxaccessibletoolbox.cxx
new file mode 100644
index 000000000..4e2059b61
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletoolbox.cxx
@@ -0,0 +1,866 @@
+/* -*- 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 <string.h>
+
+#include <standard/vclxaccessibletoolbox.hxx>
+#include <standard/vclxaccessibletoolboxitem.hxx>
+#include <toolkit/helper/convert.hxx>
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <o3tl/safeint.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/vclevent.hxx>
+#include <comphelper/accessiblewrapper.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/types.hxx>
+
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+namespace
+{
+
+ // = OToolBoxWindowItemContext
+
+ /** XAccessibleContext implementation for a toolbox item which is represented by a VCL Window
+ */
+ class OToolBoxWindowItemContext final : public OAccessibleContextWrapper
+ {
+ sal_Int32 m_nIndexInParent;
+ public:
+ OToolBoxWindowItemContext(sal_Int32 _nIndexInParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxOwningAccessible,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
+ ) : OAccessibleContextWrapper(
+ _rxContext,
+ _rxInnerAccessibleContext,
+ _rxOwningAccessible,
+ _rxParentAccessible )
+ ,m_nIndexInParent(_nIndexInParent)
+ {
+ }
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) override;
+ };
+
+
+ sal_Int32 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( )
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_nIndexInParent;
+ }
+
+
+ // = OToolBoxWindowItem
+
+ typedef ::cppu::ImplHelper1 < XUnoTunnel
+ > OToolBoxWindowItem_Base;
+
+ /** XAccessible implementation for a toolbox item which is represented by a VCL Window
+ */
+ class OToolBoxWindowItem
+ :public OAccessibleWrapper
+ ,public OToolBoxWindowItem_Base
+ {
+ private:
+ sal_Int32 m_nIndexInParent;
+
+ public:
+ sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
+ void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
+
+ static const Sequence< sal_Int8 > & getUnoTunnelId();
+
+ public:
+ OToolBoxWindowItem(sal_Int32 _nIndexInParent,
+ const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxInnerAccessible,
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
+ ) : OAccessibleWrapper(
+ _rxContext,
+ _rxInnerAccessible,
+ _rxParentAccessible)
+ ,m_nIndexInParent(_nIndexInParent)
+ {
+ }
+
+ protected:
+ // XInterface
+ DECLARE_XINTERFACE( )
+ DECLARE_XTYPEPROVIDER( )
+
+ // OAccessibleWrapper
+ virtual rtl::Reference<OAccessibleContextWrapper> createAccessibleContext(
+ const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerContext
+ ) override;
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) override;
+ };
+
+ IMPLEMENT_FORWARD_XINTERFACE2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
+
+ rtl::Reference<OAccessibleContextWrapper> OToolBoxWindowItem::createAccessibleContext(
+ const Reference< XAccessibleContext >& _rxInnerContext )
+ {
+ return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
+ }
+
+ const Sequence< sal_Int8 > & OToolBoxWindowItem::getUnoTunnelId()
+ {
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+ }
+
+ sal_Int64 SAL_CALL OToolBoxWindowItem::getSomething( const Sequence< sal_Int8 >& _rId )
+ {
+ return comphelper::getSomethingImpl(_rId, this);
+ }
+}
+
+// VCLXAccessibleToolBox
+
+VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
+
+ VCLXAccessibleComponent( pVCLXWindow )
+
+{
+}
+
+VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
+{
+}
+
+VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VCLXAccessibleToolBoxItem* pItem = nullptr;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ {
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ // returns only toolbox buttons, not windows
+ if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
+ pItem = static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
+ }
+
+ return pItem;
+}
+
+void VCLXAccessibleToolBox::UpdateFocus_Impl()
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if( !pToolBox )
+ return;
+
+ // submit events only if toolbox has the focus to avoid sending events due to mouse move
+ bool bHasFocus = false;
+ if ( pToolBox->HasFocus() )
+ bHasFocus = true;
+ else
+ {
+ // check for subtoolbar, i.e. check if our parent is a toolbar
+ ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
+ // subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
+ if ( pToolBoxParent && pToolBoxParent->HasFocus() )
+ bHasFocus = true;
+ }
+
+ if ( !bHasFocus )
+ return;
+
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ sal_uInt16 nFocusCount = 0;
+ for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
+
+ if ( rxChild.is() )
+ {
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
+ if ( pItem->HasFocus() && nItemId != nHighlightItemId )
+ {
+ // reset the old focused item
+ pItem->SetFocus( false );
+ nFocusCount++;
+ }
+ if ( nItemId == nHighlightItemId )
+ {
+ // set the new focused item
+ pItem->SetFocus( true );
+ nFocusCount++;
+ }
+ }
+ // both items changed?
+ if ( nFocusCount > 1 )
+ break;
+ }
+}
+
+void VCLXAccessibleToolBox::ReleaseFocus_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
+ {
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
+ {
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
+ if ( pItem->HasFocus() )
+ pItem->SetFocus( false );
+ }
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateChecked_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ ToolBoxItemId nFocusId = pToolBox->GetItemId( _nPos );
+ VCLXAccessibleToolBoxItem* pFocusItem = nullptr;
+
+ for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
+
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
+ pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
+ if ( nItemId == nFocusId )
+ pFocusItem = pItem;
+ }
+ //Solution:If the position is not a child item,the focus should not be called
+ if ( pFocusItem && _nPos != ToolBox::ITEM_NOTFOUND )
+ pFocusItem->SetFocus( true );
+}
+
+void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ ToolBoxItemId nItemId = pToolBox->GetItemId( _nPos );
+
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
+ {
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
+ if ( pItem )
+ pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
+ }
+}
+
+void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator const & _rMapPos,
+ bool _bNotifyRemoval )
+{
+ Reference< XAccessible > xItemAcc( _rMapPos->second );
+ if ( !xItemAcc.is() )
+ return;
+
+ if ( _bNotifyRemoval )
+ {
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any( xItemAcc ), Any() );
+ }
+
+ auto pWindowItem = comphelper::getFromUnoTunnel<OToolBoxWindowItem>(xItemAcc);
+ if ( !pWindowItem )
+ {
+ static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
+ ::comphelper::disposeComponent( xItemAcc );
+ }
+ else
+ {
+ Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
+ ::comphelper::disposeComponent( xContext );
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateItem_Impl( ToolBox::ImplToolItems::size_type _nPos)
+{
+ if ( _nPos < m_aAccessibleChildren.size() )
+ {
+ UpdateAllItems_Impl();
+ return;
+ }
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ // adjust the "index-in-parent"s
+ ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ while ( m_aAccessibleChildren.end() != aIndexAdjust )
+ {
+ Reference< XAccessible > xItemAcc( aIndexAdjust->second );
+
+ auto pWindowItem = comphelper::getFromUnoTunnel<OToolBoxWindowItem>(xItemAcc);
+ if ( !pWindowItem )
+ {
+ VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
+ if ( pItem )
+ {
+ sal_Int32 nIndex = pItem->getIndexInParent( );
+ nIndex++;
+ pItem->setIndexInParent( nIndex );
+ }
+ }
+ else
+ {
+ sal_Int32 nIndex = pWindowItem->getIndexInParent( );
+ nIndex++;
+ pWindowItem->setIndexInParent( nIndex );
+ }
+
+ ++aIndexAdjust;
+ }
+
+ // TODO: we should make this dependent on the existence of event listeners
+ // with the current implementation, we always create accessible object
+ Any aNewChild( getAccessibleChild( static_cast<sal_Int32>(_nPos) ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
+}
+
+void VCLXAccessibleToolBox::UpdateAllItems_Impl()
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ // deregister the old items
+ for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
+ aIter != m_aAccessibleChildren.end(); ++aIter )
+ {
+ implReleaseToolboxItem( aIter, true );
+ }
+ m_aAccessibleChildren.clear();
+
+ // register the new items
+ ToolBox::ImplToolItems::size_type i, nCount = pToolBox->GetItemCount();
+ for ( i = 0; i < nCount; ++i )
+ {
+ Any aNewValue;
+ aNewValue <<= getAccessibleChild( static_cast<sal_Int32>(i) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( vcl::Window* pWindow, bool bOpen )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if( !(pWindow && pToolBox) )
+ return;
+
+ const ToolBoxItemId nDownItem = pToolBox->GetDownItemId();
+ if ( !nDownItem )
+ // No item is currently in down state.
+ // Moreover, calling GetItemPos with 0 will find a separator if there is any.
+ return;
+
+ Reference< XAccessible > xChild( pWindow->GetAccessible() );
+ if( xChild.is() )
+ {
+ Reference< XAccessible > xChildItem( getAccessibleChild( static_cast< sal_Int32 >( pToolBox->GetItemPos( nDownItem ) ) ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
+
+ pItem->SetChild( xChild );
+ pItem->NotifyChildEvent( xChild, bOpen );
+ }
+}
+
+void VCLXAccessibleToolBox::UpdateItemName_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
+ if ( pItem )
+ pItem->NameChanged();
+}
+
+void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( ToolBox::ImplToolItems::size_type _nPos )
+{
+ VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
+ if ( pItem )
+ pItem->ToggleEnableState();
+}
+
+void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !(pChildWindow
+ && pToolBox
+ && pToolBox == pChildWindow->GetParent()
+ && pChildWindow->GetType() == WindowType::TOOLBOX) )
+ return;
+
+ const ToolBoxItemId nCurItemId( pToolBox->GetCurItemId() );
+ if ( !nCurItemId )
+ // No item is currently active (might happen when opening the overflow popup).
+ // Moreover, calling GetItemPos with 0 will find a separator if there is any.
+ return;
+
+ ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( nCurItemId );
+ Reference< XAccessible > xItem = getAccessibleChild( nIndex );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( xItem.is() )
+ {
+ Reference< XAccessible > xChild = pChildWindow->GetAccessible();
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
+ pItem->SetChild( xChild );
+ pItem->NotifyChildEvent( xChild, true/*_bShow*/ );
+ }
+}
+
+void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
+{
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( !pToolBox )
+ return;
+
+ ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
+ if ( nIndex == ToolBox::ITEM_NOTFOUND )
+ return; // not found
+
+ Reference< XAccessible > xItem = getAccessibleChild( nIndex );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( !xItem.is() )
+ return;
+
+ Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
+ VCLXAccessibleToolBoxItem* pItem =
+ static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
+ if ( pItem->GetChild() == xChild )
+ {
+ pItem->SetChild( Reference< XAccessible >() );
+ pItem->NotifyChildEvent( xChild, false );
+ }
+}
+
+void VCLXAccessibleToolBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
+{
+ VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ {
+ rStateSet.AddState( AccessibleStateType::FOCUSABLE );
+ if ( pToolBox->IsHorizontal() )
+ rStateSet.AddState( AccessibleStateType::HORIZONTAL );
+ else
+ rStateSet.AddState( AccessibleStateType::VERTICAL );
+ }
+}
+
+void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ // to prevent an early release of the toolbox (VclEventId::ObjectDying)
+ Reference< XAccessibleContext > xHoldAlive = this;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ToolboxClick:
+ case VclEventId::ToolboxSelect:
+ {
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( rVclWindowEvent.GetData() )
+ {
+ UpdateChecked_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ }
+ else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != ToolBox::ITEM_NOTFOUND )
+ {
+ UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
+ UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
+ }
+ break;
+ }
+ case VclEventId::ToolboxDoubleClick:
+ case VclEventId::ToolboxActivate:
+ case VclEventId::ToolboxDeactivate:
+ //case VclEventId::ToolboxSelect:
+ break;
+
+ case VclEventId::ToolboxItemUpdated:
+ {
+ if ( rVclWindowEvent.GetData() )
+ {
+ UpdateChecked_Impl( ToolBox::ITEM_NOTFOUND );
+ UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ }
+ break;
+ }
+
+ case VclEventId::ToolboxHighlight:
+ UpdateFocus_Impl();
+ break;
+
+ case VclEventId::ToolboxHighlightOff:
+ ReleaseFocus_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+
+ case VclEventId::ToolboxItemAdded :
+ UpdateItem_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+
+ case VclEventId::ToolboxItemRemoved :
+ case VclEventId::ToolboxAllItemsChanged :
+ {
+ UpdateAllItems_Impl();
+ break;
+ }
+
+ case VclEventId::ToolboxItemWindowChanged:
+ {
+ auto nPos = static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
+ ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ if ( m_aAccessibleChildren.end() != aAccessiblePos )
+ {
+ implReleaseToolboxItem( aAccessiblePos, false );
+ m_aAccessibleChildren.erase (aAccessiblePos);
+ }
+
+ Any aNewValue;
+ aNewValue <<= getAccessibleChild(nPos);
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
+ break;
+ }
+ case VclEventId::ToolboxItemTextChanged :
+ UpdateItemName_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+
+ case VclEventId::ToolboxItemEnabled :
+ case VclEventId::ToolboxItemDisabled :
+ {
+ UpdateItemEnabled_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
+ break;
+ }
+
+ case VclEventId::DropdownOpen:
+ case VclEventId::DropdownClose:
+ {
+ UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VclEventId::DropdownOpen );
+ break;
+ }
+
+ case VclEventId::ObjectDying :
+ {
+ // if this toolbox is a subtoolbox, we have to release it from its parent
+ VclPtr< vcl::Window > pWin = GetAs< vcl::Window >();
+ if ( pWin && pWin->GetParent() &&
+ pWin->GetParent()->GetType() == WindowType::TOOLBOX )
+ {
+ auto pParentAccContext = pWin->GetParent()->GetAccessible()->getAccessibleContext();
+ VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >( pParentAccContext.get() );
+ if ( pParent )
+ pParent->ReleaseSubToolBox(static_cast<ToolBox *>(pWin.get()));
+ }
+
+ // dispose all items
+ for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
+ aIter != m_aAccessibleChildren.end(); ++aIter )
+ {
+ implReleaseToolboxItem( aIter, false );
+ }
+ m_aAccessibleChildren.clear();
+
+ [[fallthrough]]; // call base class
+ }
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
+ }
+}
+
+void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow: // send create on show for direct accessible children
+ {
+ Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
+ if ( xReturn.is() )
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), Any(xReturn) );
+ else
+ HandleSubToolBarEvent( rVclWindowEvent );
+ }
+ break;
+
+ default:
+ VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
+
+ }
+}
+
+// XInterface
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
+
+// XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
+
+// XComponent
+void SAL_CALL VCLXAccessibleToolBox::disposing()
+{
+ VCLXAccessibleComponent::disposing();
+
+ // release the items
+ for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
+ aIter != m_aAccessibleChildren.end(); ++aIter )
+ {
+ implReleaseToolboxItem( aIter, false );
+ }
+ m_aAccessibleChildren.clear();
+}
+
+// XServiceInfo
+OUString VCLXAccessibleToolBox::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleToolBox";
+}
+
+Sequence< OUString > VCLXAccessibleToolBox::getSupportedServiceNames()
+{
+ return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
+ Sequence<OUString>{"com.sun.star.accessibility.AccessibleToolBox"});
+}
+
+// XAccessibleContext
+sal_Int32 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( )
+{
+ comphelper::OExternalLockGuard aGuard( this );
+ return implGetAccessibleChildCount();
+}
+
+ sal_Int32 VCLXAccessibleToolBox::implGetAccessibleChildCount( )
+ {
+ sal_Int32 nCount = 0;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ nCount = pToolBox->GetItemCount();
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+
+ return nCount;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int32 i )
+{
+ comphelper::OExternalLockGuard aGuard( this );
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( (!pToolBox) || i < 0 || o3tl::make_unsigned(i) >= pToolBox->GetItemCount() )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ // search for the child
+ ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
+ if ( m_aAccessibleChildren.end() == aIter )
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( i );
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
+ // not found -> create a new child
+ rtl::Reference<VCLXAccessibleToolBoxItem> pChild = new VCLXAccessibleToolBoxItem( pToolBox, i );
+ Reference< XAccessible> xParent = pChild;
+ if ( pItemWindow )
+ {
+ xChild = new OToolBoxWindowItem(0,::comphelper::getProcessComponentContext(),pItemWindow->GetAccessible(),xParent);
+ pItemWindow->SetAccessible(xChild);
+ pChild->SetChild( xChild );
+ }
+ xChild = pChild;
+ if ( nHighlightItemId > ToolBoxItemId(0) && nItemId == nHighlightItemId )
+ pChild->SetFocus( true );
+ if ( pToolBox->IsItemChecked( nItemId ) )
+ pChild->SetChecked( true );
+ if ( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET )
+ pChild->SetIndeterminate( true );
+ m_aAccessibleChildren.emplace( i, xChild );
+ }
+ else
+ {
+ // found it
+ xChild = aIter->second;
+ }
+ return xChild;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint )
+{
+ comphelper::OExternalLockGuard aGuard( this );
+
+ Reference< XAccessible > xAccessible;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pToolBox )
+ {
+ ToolBox::ImplToolItems::size_type nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
+ if ( nItemPos != ToolBox::ITEM_NOTFOUND )
+ xAccessible = getAccessibleChild( nItemPos );
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ }
+
+ return xAccessible;
+}
+
+Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
+{
+ Reference< XAccessible > xReturn;
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( pChildWindow && pToolBox )
+ {
+ ToolBox::ImplToolItems::size_type nCount = pToolBox->GetItemCount();
+ for (ToolBox::ImplToolItems::size_type i = 0 ; i < nCount && !xReturn.is() ; ++i)
+ {
+ ToolBoxItemId nItemId = pToolBox->GetItemId( i );
+ vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
+ if ( pItemWindow == pChildWindow )
+ xReturn = getAccessibleChild(i);
+ //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
+ }
+ }
+ return xReturn;
+}
+
+Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
+{
+ Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
+
+ if ( !xReturn.is() )
+ xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
+ return xReturn;
+}
+
+// XAccessibleSelection
+void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
+ throw IndexOutOfBoundsException();
+
+ pToolBox->ChangeHighlight( nChildIndex );
+}
+
+sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
+ throw IndexOutOfBoundsException();
+
+ if ( pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nChildIndex ) )
+ return true;
+ else
+ return false;
+}
+
+void VCLXAccessibleToolBox::clearAccessibleSelection( )
+{
+ OExternalLockGuard aGuard( this );
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ pToolBox -> LoseFocus();
+}
+
+void VCLXAccessibleToolBox::selectAllAccessibleChildren( )
+{
+ OExternalLockGuard aGuard( this );
+ // intentionally empty. makes no sense for a toolbox
+}
+
+sal_Int32 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nRet = 0;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if (pToolBox)
+ {
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ for ( size_t i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
+ {
+ if ( nHighlightItemId == pToolBox->GetItemId( i ) )
+ {
+ nRet = 1;
+ break; // a toolbox can only have (n)one selected child
+ }
+ }
+ }
+
+ return nRet;
+}
+
+Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+ if ( nSelectedChildIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ Reference< XAccessible > xChild;
+ VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
+ if (pToolBox)
+ {
+ ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
+ for ( sal_Int32 i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
+ {
+ if ( nHighlightItemId == pToolBox->GetItemId( i ) )
+ {
+ xChild = getAccessibleChild( i );
+ break;
+ }
+ }
+ }
+
+ if (!xChild)
+ throw IndexOutOfBoundsException();
+
+ return xChild;
+}
+
+void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int32 nChildIndex )
+{
+ OExternalLockGuard aGuard( this );
+ if ( nChildIndex < 0 || nChildIndex >= implGetAccessibleChildCount() )
+ throw IndexOutOfBoundsException();
+ clearAccessibleSelection(); // a toolbox can only have (n)one selected child
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/accessibility/source/standard/vclxaccessibletoolboxitem.cxx b/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
new file mode 100644
index 000000000..dd2a44628
--- /dev/null
+++ b/accessibility/source/standard/vclxaccessibletoolboxitem.cxx
@@ -0,0 +1,734 @@
+/* -*- 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 <standard/vclxaccessibletoolboxitem.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/accresmgr.hxx>
+#include <strings.hrc>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
+#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/unohelp2.hxx>
+#include <vcl/help.hxx>
+#include <vcl/settings.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <strings.hxx>
+#include <sal/log.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+
+#include <array>
+
+// class VCLXAccessibleToolBoxItem ------------------------------------------
+
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+
+// Ctor() and Dtor()
+
+VCLXAccessibleToolBoxItem::VCLXAccessibleToolBoxItem( ToolBox* _pToolBox, sal_Int32 _nPos ) :
+ m_pToolBox ( _pToolBox ),
+ m_nIndexInParent( _nPos ),
+ m_nRole ( AccessibleRole::PUSH_BUTTON ),
+ m_nItemId ( 0 ),
+ m_bHasFocus ( false ),
+ m_bIsChecked ( false ),
+ m_bIndeterminate( false )
+
+{
+ OSL_ENSURE( m_pToolBox, "invalid toolbox" );
+ m_nItemId = m_pToolBox->GetItemId( m_nIndexInParent );
+ m_sOldName = GetText();
+ m_bIsChecked = m_pToolBox->IsItemChecked( m_nItemId );
+ m_bIndeterminate = ( m_pToolBox->GetItemState( m_nItemId ) == TRISTATE_INDET );
+ ToolBoxItemType eType = m_pToolBox->GetItemType( m_nIndexInParent );
+ switch ( eType )
+ {
+ case ToolBoxItemType::BUTTON :
+ {
+ ToolBoxItemBits nBits = m_pToolBox->GetItemBits( m_nItemId );
+ if (
+ (( nBits & ToolBoxItemBits::DROPDOWN ) == ToolBoxItemBits::DROPDOWN) ||
+ (( nBits & ToolBoxItemBits::DROPDOWNONLY ) == ToolBoxItemBits::DROPDOWNONLY)
+ )
+ m_nRole = AccessibleRole::BUTTON_DROPDOWN;
+ else if (
+ ( ( nBits & ToolBoxItemBits::CHECKABLE ) == ToolBoxItemBits::CHECKABLE ) ||
+ ( ( nBits & ToolBoxItemBits::RADIOCHECK ) == ToolBoxItemBits::RADIOCHECK ) ||
+ ( ( nBits & ToolBoxItemBits::AUTOCHECK ) == ToolBoxItemBits::AUTOCHECK )
+ )
+ m_nRole = AccessibleRole::TOGGLE_BUTTON;
+ else if ( m_pToolBox->GetItemWindow( m_nItemId ) )
+ m_nRole = AccessibleRole::PANEL;
+ break;
+ }
+
+ case ToolBoxItemType::SPACE :
+ m_nRole = AccessibleRole::FILLER;
+ break;
+
+ case ToolBoxItemType::SEPARATOR :
+ case ToolBoxItemType::BREAK :
+ m_nRole = AccessibleRole::SEPARATOR;
+ break;
+
+ default:
+ {
+ SAL_WARN( "accessibility", "unsupported toolbox itemtype" );
+ }
+ }
+}
+
+VCLXAccessibleToolBoxItem::~VCLXAccessibleToolBoxItem()
+{
+}
+
+OUString VCLXAccessibleToolBoxItem::GetText() const
+{
+ OUString sRet;
+ // no text for separators and spaces
+ if ( m_pToolBox && m_nItemId > ToolBoxItemId(0) )
+ {
+ sRet = m_pToolBox->GetItemText( m_nItemId );
+ if (sRet.isEmpty())
+ {
+ sRet = m_pToolBox->GetQuickHelpText( m_nItemId );
+ if (sRet.isEmpty())
+ {
+ vcl::Window* pItemWindow = m_pToolBox->GetItemWindow( m_nItemId );
+ if ( m_nRole == AccessibleRole::PANEL && pItemWindow && pItemWindow->GetAccessible().is() &&
+ pItemWindow->GetAccessible()->getAccessibleContext().is() )
+ {
+ OUString sWinText = pItemWindow->GetAccessible()->getAccessibleContext()->getAccessibleName();
+ if (!sWinText.isEmpty())
+ sRet = sWinText;
+ }
+ }
+ }
+
+ }
+ return sRet;
+}
+
+void VCLXAccessibleToolBoxItem::SetFocus( bool _bFocus )
+{
+ if ( m_bHasFocus != _bFocus )
+ {
+ Any aOldValue;
+ Any aNewValue;
+ if ( m_bHasFocus )
+ aOldValue <<= AccessibleStateType::FOCUSED;
+ else
+ aNewValue <<= AccessibleStateType::FOCUSED;
+ m_bHasFocus = _bFocus;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::SetChecked( bool _bCheck )
+{
+ if( m_nRole == AccessibleRole::PANEL)
+ return;
+ if ( m_bIsChecked != _bCheck )
+ {
+ Any aOldValue;
+ Any aNewValue;
+ if ( m_bIsChecked )
+ aOldValue <<= AccessibleStateType::CHECKED;
+ else
+ aNewValue <<= AccessibleStateType::CHECKED;
+ m_bIsChecked = _bCheck;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::SetIndeterminate( bool _bIndeterminate )
+{
+ if ( m_bIndeterminate != _bIndeterminate )
+ {
+ Any aOldValue, aNewValue;
+ if ( m_bIndeterminate )
+ aOldValue <<= AccessibleStateType::INDETERMINATE;
+ else
+ aNewValue <<= AccessibleStateType::INDETERMINATE;
+ m_bIndeterminate = _bIndeterminate;
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::NameChanged()
+{
+ OUString sNewName = implGetText();
+ if ( sNewName != m_sOldName )
+ {
+ Any aOldValue, aNewValue;
+ aOldValue <<= m_sOldName;
+ // save new name as old name for next change
+ m_sOldName = sNewName;
+ aNewValue <<= m_sOldName;
+ NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+}
+
+void VCLXAccessibleToolBoxItem::SetChild( const Reference< XAccessible >& _xChild )
+{
+ m_xChild = _xChild;
+}
+
+void VCLXAccessibleToolBoxItem::NotifyChildEvent( const Reference< XAccessible >& _xChild, bool _bShow )
+{
+ Any aOld = _bShow ? Any() : Any( _xChild );
+ Any aNew = _bShow ? Any( _xChild ) : Any();
+ NotifyAccessibleEvent( AccessibleEventId::CHILD, aOld, aNew );
+}
+
+void VCLXAccessibleToolBoxItem::ToggleEnableState()
+{
+ std::array<Any, 2> aOldValue, aNewValue;
+ if ( m_pToolBox->IsItemEnabled( m_nItemId ) )
+ {
+ aNewValue[0] <<= AccessibleStateType::SENSITIVE;
+ aNewValue[1] <<= AccessibleStateType::ENABLED;
+ }
+ else
+ {
+ aOldValue[0] <<= AccessibleStateType::ENABLED;
+ aOldValue[1] <<= AccessibleStateType::SENSITIVE;
+ }
+
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
+ NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
+}
+
+awt::Rectangle VCLXAccessibleToolBoxItem::implGetBounds( )
+{
+ awt::Rectangle aRect;
+ if ( m_pToolBox )
+ aRect = AWTRectangle( m_pToolBox->GetItemPosRect( m_nIndexInParent ) );
+
+ return aRect;
+}
+
+OUString VCLXAccessibleToolBoxItem::implGetText()
+{
+ return GetText();
+}
+
+Locale VCLXAccessibleToolBoxItem::implGetLocale()
+{
+ return Application::GetSettings().GetUILanguageTag().getLocale();
+}
+
+void VCLXAccessibleToolBoxItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
+{
+ nStartIndex = 0;
+ nEndIndex = 0;
+}
+
+// XInterface
+
+IMPLEMENT_FORWARD_REFCOUNT( VCLXAccessibleToolBoxItem, AccessibleTextHelper_BASE )
+Any SAL_CALL VCLXAccessibleToolBoxItem::queryInterface( const Type& _rType )
+{
+ // #i33611# - toolbox buttons without text don't support XAccessibleText
+ if ( _rType == cppu::UnoType<XAccessibleText>::get()
+ && ( !m_pToolBox || m_pToolBox->GetButtonType() == ButtonType::SYMBOLONLY ) )
+ return Any();
+
+ css::uno::Any aReturn = AccessibleTextHelper_BASE::queryInterface( _rType );
+ if ( !aReturn.hasValue() )
+ aReturn = VCLXAccessibleToolBoxItem_BASE::queryInterface( _rType );
+ return aReturn;
+}
+
+// XTypeProvider
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBoxItem, AccessibleTextHelper_BASE, VCLXAccessibleToolBoxItem_BASE )
+
+// XComponent
+
+void SAL_CALL VCLXAccessibleToolBoxItem::disposing()
+{
+ AccessibleTextHelper_BASE::disposing();
+ m_pToolBox = nullptr;
+}
+
+// XServiceInfo
+
+OUString VCLXAccessibleToolBoxItem::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleToolBoxItem";
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > VCLXAccessibleToolBoxItem::getSupportedServiceNames()
+{
+ return {"com.sun.star.accessibility.AccessibleContext",
+ "com.sun.star.accessibility.AccessibleComponent",
+ "com.sun.star.accessibility.AccessibleExtendedComponent",
+ "com.sun.star.accessibility.AccessibleToolBoxItem"};
+}
+
+// XAccessible
+
+Reference< XAccessibleContext > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleContext( )
+{
+ return this;
+}
+
+// XAccessibleContext
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleChildCount( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_xChild.is() ? 1 : 0;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleChild( sal_Int32 i )
+{
+ OContextEntryGuard aGuard( this );
+
+ // no child -> so index is out of bounds
+ if ( !m_xChild.is() || i != 0 )
+ throw IndexOutOfBoundsException();
+
+ return m_xChild;
+}
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleParent( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_pToolBox->GetAccessible();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleIndexInParent( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_nIndexInParent;
+}
+
+sal_Int16 SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleRole( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return m_nRole;
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ if (m_nRole == AccessibleRole::PANEL && m_xChild.is())
+ {
+ return AccResId( RID_STR_ACC_PANEL_DESCRIPTION );
+ }
+ else
+ {
+ OUString sDescription;
+ if ( m_pToolBox )
+ sDescription = m_pToolBox->GetHelpText( m_nItemId );
+ return sDescription;
+ }
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ // entry text == accessible name
+ return GetText();
+}
+
+Reference< XAccessibleRelationSet > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleRelationSet( )
+{
+ OContextEntryGuard aGuard( this );
+
+ return new utl::AccessibleRelationSetHelper;
+}
+
+Reference< XAccessibleStateSet > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper;
+
+ if ( m_pToolBox && !rBHelper.bDisposed && !rBHelper.bInDispose )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
+ if ( m_bIsChecked && m_nRole != AccessibleRole::PANEL )
+ pStateSetHelper->AddState( AccessibleStateType::CHECKED );
+ if ( m_bIndeterminate )
+ pStateSetHelper->AddState( AccessibleStateType::INDETERMINATE );
+ if ( m_pToolBox->IsEnabled() && m_pToolBox->IsItemEnabled( m_nItemId ) )
+ {
+ pStateSetHelper->AddState( AccessibleStateType::ENABLED );
+ pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
+ }
+ if ( m_pToolBox->IsItemVisible( m_nItemId ) )
+ pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
+ if ( m_pToolBox->IsItemReallyVisible( m_nItemId ) )
+ pStateSetHelper->AddState( AccessibleStateType::SHOWING );
+ if ( m_bHasFocus )
+ pStateSetHelper->AddState( AccessibleStateType::FOCUSED );
+ }
+ else
+ pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
+
+ return pStateSetHelper;
+}
+
+// XAccessibleText
+
+OUString VCLXAccessibleToolBoxItem::getText()
+{
+ OExternalLockGuard aGuard( this );
+
+ return GetText();
+}
+
+sal_Int32 VCLXAccessibleToolBoxItem::getCharacterCount()
+{
+ return GetText().getLength();
+}
+
+sal_Unicode VCLXAccessibleToolBoxItem::getCharacter( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetCharacter( GetText(), nIndex );
+}
+
+OUString VCLXAccessibleToolBoxItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ return OCommonAccessibleText::implGetTextRange( GetText(), nStartIndex, nEndIndex );
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getCaretPosition()
+{
+ return -1;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleToolBoxItem::setCaretPosition( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nIndex, nIndex, GetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+Sequence< PropertyValue > SAL_CALL VCLXAccessibleToolBoxItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return Sequence< PropertyValue >();
+}
+
+awt::Rectangle SAL_CALL VCLXAccessibleToolBoxItem::getCharacterBounds( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sText( implGetText() );
+
+ if ( !implIsValidIndex( nIndex, sText.getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( m_pToolBox && m_pToolBox->GetButtonType() != ButtonType::SYMBOLONLY ) // symbol buttons have no character bounds
+ {
+ tools::Rectangle aCharRect = m_pToolBox->GetCharacterBounds( m_nItemId, nIndex );
+ tools::Rectangle aItemRect = m_pToolBox->GetItemRect( m_nItemId );
+ aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
+ aBounds = AWTRectangle( aCharRect );
+ }
+
+ return aBounds;
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getIndexAtPoint( const awt::Point& aPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int32 nIndex = -1;
+ if ( m_pToolBox && m_pToolBox->GetButtonType() != ButtonType::SYMBOLONLY ) // symbol buttons have no character bounds
+ {
+ ToolBoxItemId nItemId;
+ tools::Rectangle aItemRect = m_pToolBox->GetItemRect( m_nItemId );
+ Point aPnt( VCLPoint( aPoint ) );
+ aPnt += aItemRect.TopLeft();
+ sal_Int32 nIdx = m_pToolBox->GetIndexForPoint( aPnt, nItemId );
+ if ( nIdx != -1 && nItemId == m_nItemId )
+ nIndex = nIdx;
+ }
+
+ return nIndex;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleToolBoxItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ return false;
+}
+
+sal_Bool SAL_CALL VCLXAccessibleToolBoxItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
+ throw IndexOutOfBoundsException();
+
+ bool bReturn = false;
+
+ if ( m_pToolBox )
+ {
+ Reference< datatransfer::clipboard::XClipboard > xClipboard = m_pToolBox->GetClipboard();
+ if ( xClipboard.is() )
+ {
+ OUString sText( OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex ) );
+
+ rtl::Reference<vcl::unohelper::TextDataObject> pDataObj = new vcl::unohelper::TextDataObject( sText );
+
+ SolarMutexReleaser aReleaser;
+ xClipboard->setContents( pDataObj, nullptr );
+
+ Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
+ if( xFlushableClipboard.is() )
+ xFlushableClipboard->flushClipboard();
+
+ bReturn = true;
+ }
+ }
+
+ return bReturn;
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
+{
+ return false;
+}
+
+// XAccessibleComponent
+
+Reference< XAccessible > SAL_CALL VCLXAccessibleToolBoxItem::getAccessibleAtPoint( const awt::Point& )
+{
+ return Reference< XAccessible >();
+}
+
+void SAL_CALL VCLXAccessibleToolBoxItem::grabFocus( )
+{
+ Reference< XAccessible > xParent(getAccessibleParent());
+
+ if( xParent.is() )
+ {
+ Reference< XAccessibleSelection > rxAccessibleSelection(xParent->getAccessibleContext(), UNO_QUERY);
+
+ if ( rxAccessibleSelection.is() )
+ {
+ rxAccessibleSelection -> selectAccessibleChild ( getAccessibleIndexInParent() );
+ }
+ }
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ if ( m_pToolBox )
+ nColor = m_pToolBox->GetControlForeground();
+
+ return sal_Int32(nColor);
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleToolBoxItem::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ if ( m_pToolBox )
+ nColor = m_pToolBox->GetControlBackground();
+
+ return sal_Int32(nColor);
+}
+
+// XAccessibleExtendedComponent
+Reference< awt::XFont > SAL_CALL VCLXAccessibleToolBoxItem::getFont( )
+{
+ return uno::Reference< awt::XFont >();
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( m_pToolBox )
+ sRet = m_pToolBox->GetItemText( m_nItemId );
+
+ return sRet;
+}
+
+OUString SAL_CALL VCLXAccessibleToolBoxItem::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( m_pToolBox )
+ {
+ if ( Help::IsExtHelpEnabled() )
+ sRet = m_pToolBox->GetHelpText( m_nItemId );
+ else
+ sRet = m_pToolBox->GetQuickHelpText( m_nItemId );
+ if ( sRet.isEmpty() )
+ // no help text set, so use item text
+ sRet = m_pToolBox->GetItemText( m_nItemId );
+ }
+ return sRet;
+}
+
+// XAccessibleAction
+
+sal_Int32 VCLXAccessibleToolBoxItem::getAccessibleActionCount( )
+{
+ // only one action -> "Click"
+ return 1;
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::doAccessibleAction ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ if ( m_pToolBox )
+ m_pToolBox->TriggerItem( m_nItemId );
+
+ return true;
+}
+
+OUString VCLXAccessibleToolBoxItem::getAccessibleActionDescription ( sal_Int32 nIndex )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return RID_STR_ACC_ACTION_CLICK;
+}
+
+Reference< XAccessibleKeyBinding > VCLXAccessibleToolBoxItem::getAccessibleActionKeyBinding( sal_Int32 nIndex )
+{
+ OContextEntryGuard aGuard( this );
+
+ if ( nIndex != 0 )
+ throw IndexOutOfBoundsException();
+
+ return Reference< XAccessibleKeyBinding >();
+}
+
+// XAccessibleValue
+
+Any VCLXAccessibleToolBoxItem::getCurrentValue( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Any aValue;
+ if ( m_pToolBox )
+ aValue <<= static_cast<sal_Int32>(m_pToolBox->IsItemChecked( m_nItemId ));
+
+ if( m_nRole == AccessibleRole::PANEL )
+ aValue <<= sal_Int32(0);
+ return aValue;
+}
+
+sal_Bool VCLXAccessibleToolBoxItem::setCurrentValue( const Any& aNumber )
+{
+ OExternalLockGuard aGuard( this );
+
+ bool bReturn = false;
+
+ if ( m_pToolBox )
+ {
+ sal_Int32 nValue = 0;
+ OSL_VERIFY( aNumber >>= nValue );
+
+ if ( nValue < 0 )
+ nValue = 0;
+ else if ( nValue > 1 )
+ nValue = 1;
+
+ m_pToolBox->CheckItem( m_nItemId, nValue == 1 );
+ bReturn = true;
+ }
+
+ return bReturn;
+}
+
+Any VCLXAccessibleToolBoxItem::getMaximumValue( )
+{
+ return Any(sal_Int32(1));
+}
+
+Any VCLXAccessibleToolBoxItem::getMinimumValue( )
+{
+ return Any(sal_Int32(0));
+}
+
+Any VCLXAccessibleToolBoxItem::getMinimumIncrement( )
+{
+ return Any(sal_Int32(1));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */