1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <extended/AccessibleBrowseBoxBase.hxx>
22 #include <vcl/accessibletableprovider.hxx>
23 #include <cppuhelper/supportsservice.hxx>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
29 #include <unotools/accessiblerelationsethelper.hxx>
30 #include <vcl/unohelp.hxx>
31 #include <vcl/window.hxx>
32 #include <vcl/svapp.hxx>
33 #include <sal/log.hxx>
36 using ::com::sun::star::uno::Reference
;
37 using ::com::sun::star::uno::Sequence
;
38 using ::com::sun::star::uno::Any
;
40 using namespace ::com::sun::star
;
41 using namespace ::com::sun::star::accessibility
;
42 using namespace ::comphelper
;
45 namespace accessibility
{
47 using namespace com::sun::star::accessibility::AccessibleStateType
;
50 // Ctor/Dtor/disposing
52 AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
53 const css::uno::Reference
<css::accessibility::XAccessible
>& xParent
,
54 ::vcl::IAccessibleTableProvider
& rBrowseBox
,
55 const css::uno::Reference
<css::awt::XWindow
>& xFocusWindow
, AccessibleBrowseBoxObjType eObjType
)
56 : AccessibleBrowseBoxBase(xParent
, rBrowseBox
, xFocusWindow
, eObjType
,
57 rBrowseBox
.GetAccessibleObjectName(eObjType
),
58 rBrowseBox
.GetAccessibleObjectDescription(eObjType
))
62 AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
63 css::uno::Reference
< css::accessibility::XAccessible
> rxParent
,
64 ::vcl::IAccessibleTableProvider
& rBrowseBox
,
65 css::uno::Reference
< css::awt::XWindow
> _xFocusWindow
,
66 AccessibleBrowseBoxObjType eObjType
,
68 OUString rDescription
) :
69 AccessibleBrowseBoxImplHelper( m_aMutex
),
70 mxParent(std::move( rxParent
)),
71 mpBrowseBox( &rBrowseBox
),
72 m_xFocusWindow(std::move(_xFocusWindow
)),
73 maName(std::move( rName
)),
74 maDescription(std::move( rDescription
)),
75 meObjType( eObjType
),
78 if ( m_xFocusWindow
.is() )
79 m_xFocusWindow
->addFocusListener( this );
82 AccessibleBrowseBoxBase::~AccessibleBrowseBoxBase()
86 // increment ref count to prevent double call of Dtor
87 osl_atomic_increment( &m_refCount
);
92 void SAL_CALL
AccessibleBrowseBoxBase::disposing()
94 ::osl::MutexGuard
aGuard( getMutex() );
95 if ( m_xFocusWindow
.is() )
97 SolarMutexGuard aSolarGuard
;
98 m_xFocusWindow
->removeFocusListener( this );
101 if ( getClientId( ) )
103 AccessibleEventNotifier::TClientId
nId( getClientId( ) );
105 AccessibleEventNotifier::revokeClientNotifyDisposing( nId
, *this );
109 mpBrowseBox
= nullptr;
112 // css::accessibility::XAccessibleContext
114 Reference
< css::accessibility::XAccessible
> SAL_CALL
AccessibleBrowseBoxBase::getAccessibleParent()
116 ::osl::MutexGuard
aGuard( getMutex() );
121 sal_Int64 SAL_CALL
AccessibleBrowseBoxBase::getAccessibleIndexInParent()
123 ::osl::MutexGuard
aGuard( getMutex() );
126 // -1 for child not found/no parent (according to specification)
129 css::uno::Reference
< uno::XInterface
> xMeMyselfAndI( static_cast< css::accessibility::XAccessibleContext
* >( this ), uno::UNO_QUERY
);
131 // iterate over parent's children and search for this object
134 css::uno::Reference
< css::accessibility::XAccessibleContext
>
135 xParentContext( mxParent
->getAccessibleContext() );
136 if( xParentContext
.is() )
138 css::uno::Reference
< uno::XInterface
> xChild
;
140 sal_Int64 nChildCount
= xParentContext
->getAccessibleChildCount();
141 for( sal_Int64 nChild
= 0; nChild
< nChildCount
; ++nChild
)
143 xChild
.set(xParentContext
->getAccessibleChild( nChild
), css::uno::UNO_QUERY
);
145 if ( xMeMyselfAndI
.get() == xChild
.get() )
156 OUString SAL_CALL
AccessibleBrowseBoxBase::getAccessibleDescription()
158 ::osl::MutexGuard
aGuard( getMutex() );
160 return maDescription
;
163 OUString SAL_CALL
AccessibleBrowseBoxBase::getAccessibleName()
165 ::osl::MutexGuard
aGuard( getMutex() );
170 Reference
< css::accessibility::XAccessibleRelationSet
> SAL_CALL
171 AccessibleBrowseBoxBase::getAccessibleRelationSet()
173 ::osl::MutexGuard
aGuard( getMutex() );
175 // BrowseBox does not have relations.
176 return new utl::AccessibleRelationSetHelper
;
180 AccessibleBrowseBoxBase::getAccessibleStateSet()
182 SolarMethodGuard
aGuard( getMutex() );
183 // don't check whether alive -> StateSet may contain DEFUNC
184 return implCreateStateSet();
187 lang::Locale SAL_CALL
AccessibleBrowseBoxBase::getLocale()
189 ::osl::MutexGuard
aGuard( getMutex() );
193 css::uno::Reference
< css::accessibility::XAccessibleContext
>
194 xParentContext( mxParent
->getAccessibleContext() );
195 if( xParentContext
.is() )
196 return xParentContext
->getLocale();
198 throw IllegalAccessibleComponentStateException();
201 // css::accessibility::XAccessibleComponent
203 sal_Bool SAL_CALL
AccessibleBrowseBoxBase::containsPoint( const css::awt::Point
& rPoint
)
205 return tools::Rectangle(Point(), getBoundingBox().GetSize())
206 .Contains(vcl::unohelper::ConvertToVCLPoint(rPoint
));
209 awt::Rectangle SAL_CALL
AccessibleBrowseBoxBase::getBounds()
211 return vcl::unohelper::ConvertToAWTRect(getBoundingBox());
214 awt::Point SAL_CALL
AccessibleBrowseBoxBase::getLocation()
216 return vcl::unohelper::ConvertToAWTPoint(getBoundingBox().TopLeft());
219 awt::Point SAL_CALL
AccessibleBrowseBoxBase::getLocationOnScreen()
221 return vcl::unohelper::ConvertToAWTPoint(getBoundingBoxOnScreen().TopLeft());
224 awt::Size SAL_CALL
AccessibleBrowseBoxBase::getSize()
226 return vcl::unohelper::ConvertToAWTSize(getBoundingBox().GetSize());
229 void SAL_CALL
AccessibleBrowseBoxBase::focusGained( const css::awt::FocusEvent
& )
231 css::uno::Any aFocused
;
232 css::uno::Any aEmpty
;
233 aFocused
<<= FOCUSED
;
235 commitEvent(AccessibleEventId::STATE_CHANGED
,aFocused
,aEmpty
);
239 void SAL_CALL
AccessibleBrowseBoxBase::focusLost( const css::awt::FocusEvent
& )
241 css::uno::Any aFocused
;
242 css::uno::Any aEmpty
;
243 aFocused
<<= FOCUSED
;
245 commitEvent(AccessibleEventId::STATE_CHANGED
,aEmpty
,aFocused
);
247 // css::accessibility::XAccessibleEventBroadcaster
249 void SAL_CALL
AccessibleBrowseBoxBase::addAccessibleEventListener(
250 const css::uno::Reference
< css::accessibility::XAccessibleEventListener
>& _rxListener
)
252 if ( _rxListener
.is() )
254 ::osl::MutexGuard
aGuard( getMutex() );
255 if ( !getClientId( ) )
256 setClientId( AccessibleEventNotifier::registerClient( ) );
258 AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener
);
262 void SAL_CALL
AccessibleBrowseBoxBase::removeAccessibleEventListener(
263 const css::uno::Reference
< css::accessibility::XAccessibleEventListener
>& _rxListener
)
265 if( !(_rxListener
.is() && getClientId( )) )
268 ::osl::MutexGuard
aGuard( getMutex() );
269 sal_Int32 nListenerCount
= AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener
);
270 if ( !nListenerCount
)
272 // no listeners anymore
273 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
274 // and at least to us not firing any events anymore, in case somebody calls
275 // NotifyAccessibleEvent, again
277 AccessibleEventNotifier::TClientId
nId( getClientId( ) );
279 AccessibleEventNotifier::revokeClient( nId
);
285 Sequence
< sal_Int8
> SAL_CALL
AccessibleBrowseBoxBase::getImplementationId()
287 return css::uno::Sequence
<sal_Int8
>();
292 sal_Bool SAL_CALL
AccessibleBrowseBoxBase::supportsService(
293 const OUString
& rServiceName
)
295 return cppu::supportsService(this, rServiceName
);
298 Sequence
< OUString
> SAL_CALL
AccessibleBrowseBoxBase::getSupportedServiceNames()
300 return { u
"com.sun.star.accessibility.AccessibleContext"_ustr
};
303 // other public methods
305 void AccessibleBrowseBoxBase::setAccessibleName( const OUString
& rName
)
307 ::osl::ClearableMutexGuard
aGuard( getMutex() );
315 AccessibleEventId::NAME_CHANGED
,
320 void AccessibleBrowseBoxBase::setAccessibleDescription( const OUString
& rDescription
)
322 ::osl::ClearableMutexGuard
aGuard( getMutex() );
324 aOld
<<= maDescription
;
325 maDescription
= rDescription
;
330 AccessibleEventId::DESCRIPTION_CHANGED
,
331 uno::Any( maDescription
),
335 // internal virtual methods
337 bool AccessibleBrowseBoxBase::implIsShowing()
339 bool bShowing
= false;
342 css::uno::Reference
< css::accessibility::XAccessibleComponent
>
343 xParentComp( mxParent
->getAccessibleContext(), uno::UNO_QUERY
);
344 if( xParentComp
.is() )
345 bShowing
= implGetBoundingBox().Overlaps(
346 vcl::unohelper::ConvertToVCLRect(xParentComp
->getBounds()));
351 sal_Int64
AccessibleBrowseBoxBase::implCreateStateSet()
353 sal_Int64 nStateSet
= 0;
357 // SHOWING done with mxParent
358 if( implIsShowing() )
359 nStateSet
|= AccessibleStateType::SHOWING
;
360 // BrowseBox fills StateSet with states depending on object type
361 mpBrowseBox
->FillAccessibleStateSet( nStateSet
, getType() );
364 nStateSet
|= AccessibleStateType::DEFUNC
;
369 // internal helper methods
371 bool AccessibleBrowseBoxBase::isAlive() const
373 return !rBHelper
.bDisposed
&& !rBHelper
.bInDispose
&& mpBrowseBox
;
376 void AccessibleBrowseBoxBase::ensureIsAlive() const
379 throw lang::DisposedException();
382 tools::Rectangle
AccessibleBrowseBoxBase::getBoundingBox()
384 SolarMethodGuard
aGuard(getMutex());
387 tools::Rectangle aRect
= implGetBoundingBox();
388 if ( aRect
.Left() == 0 && aRect
.Top() == 0 && aRect
.Right() == 0 && aRect
.Bottom() == 0 )
390 SAL_WARN( "accessibility", "rectangle doesn't exist" );
395 AbsoluteScreenPixelRectangle
AccessibleBrowseBoxBase::getBoundingBoxOnScreen()
397 SolarMethodGuard
aGuard(getMutex());
400 AbsoluteScreenPixelRectangle aRect
= implGetBoundingBoxOnScreen();
401 if ( aRect
.Left() == 0 && aRect
.Top() == 0 && aRect
.Right() == 0 && aRect
.Bottom() == 0 )
403 SAL_WARN( "accessibility", "rectangle doesn't exist" );
408 void AccessibleBrowseBoxBase::commitEvent(
409 sal_Int16 _nEventId
, const Any
& _rNewValue
, const Any
& _rOldValue
)
411 osl::MutexGuard
aGuard( getMutex() );
412 if ( !getClientId( ) )
413 // if we don't have a client id for the notifier, then we don't have listeners, then
414 // we don't need to notify anything
417 // build an event object
418 AccessibleEventObject
aEvent(*this, _nEventId
, _rNewValue
, _rOldValue
, -1);
420 // let the notifier handle this event
422 AccessibleEventNotifier::addEvent( getClientId( ), aEvent
);
425 sal_Int16 SAL_CALL
AccessibleBrowseBoxBase::getAccessibleRole()
427 osl::MutexGuard
aGuard( getMutex() );
429 sal_Int16 nRole
= AccessibleRole::UNKNOWN
;
432 case AccessibleBrowseBoxObjType::RowHeaderCell
:
433 nRole
= AccessibleRole::ROW_HEADER
;
435 case AccessibleBrowseBoxObjType::ColumnHeaderCell
:
436 nRole
= AccessibleRole::COLUMN_HEADER
;
438 case AccessibleBrowseBoxObjType::ColumnHeaderBar
:
439 case AccessibleBrowseBoxObjType::RowHeaderBar
:
440 case AccessibleBrowseBoxObjType::Table
:
441 nRole
= AccessibleRole::TABLE
;
443 case AccessibleBrowseBoxObjType::TableCell
:
444 nRole
= AccessibleRole::TABLE_CELL
;
446 case AccessibleBrowseBoxObjType::BrowseBox
:
447 nRole
= AccessibleRole::PANEL
;
449 case AccessibleBrowseBoxObjType::CheckBoxCell
:
450 nRole
= AccessibleRole::CHECK_BOX
;
456 Reference
<XAccessible
> SAL_CALL
AccessibleBrowseBoxBase::getAccessibleAtPoint( const css::awt::Point
& )
461 void SAL_CALL
AccessibleBrowseBoxBase::disposing( const css::lang::EventObject
& )
463 m_xFocusWindow
= nullptr;
466 sal_Int32 SAL_CALL
AccessibleBrowseBoxBase::getForeground( )
468 SolarMethodGuard
aGuard(getMutex());
472 vcl::Window
* pInst
= mpBrowseBox
->GetWindowInstance();
475 if ( pInst
->IsControlForeground() )
476 nColor
= pInst
->GetControlForeground();
480 if ( pInst
->IsControlFont() )
481 aFont
= pInst
->GetControlFont();
483 aFont
= pInst
->GetFont();
484 nColor
= aFont
.GetColor();
488 return sal_Int32(nColor
);
491 sal_Int32 SAL_CALL
AccessibleBrowseBoxBase::getBackground( )
493 SolarMethodGuard
aGuard(getMutex());
497 vcl::Window
* pInst
= mpBrowseBox
->GetWindowInstance();
500 if ( pInst
->IsControlBackground() )
501 nColor
= pInst
->GetControlBackground();
503 nColor
= pInst
->GetBackground().GetColor();
506 return sal_Int32(nColor
);
510 // css::accessibility::XAccessible
512 Reference
< css::accessibility::XAccessibleContext
> SAL_CALL
BrowseBoxAccessibleElement::getAccessibleContext()
514 osl::MutexGuard
aGuard( getMutex() );
520 BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const css::uno::Reference
< css::accessibility::XAccessible
>& rxParent
, ::vcl::IAccessibleTableProvider
& rBrowseBox
,
521 AccessibleBrowseBoxObjType eObjType
)
522 : BrowseBoxAccessibleElement_Base(rxParent
, rBrowseBox
, nullptr, eObjType
)
527 BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const css::uno::Reference
< css::accessibility::XAccessible
>& rxParent
, ::vcl::IAccessibleTableProvider
& rBrowseBox
,
528 AccessibleBrowseBoxObjType eObjType
, const OUString
& rName
, const OUString
& rDescription
)
529 : BrowseBoxAccessibleElement_Base(rxParent
, rBrowseBox
, nullptr, eObjType
, rName
, rDescription
)
534 BrowseBoxAccessibleElement::~BrowseBoxAccessibleElement( )
539 } // namespace accessibility
542 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */