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 "AccessibleContextBase.hxx"
21 #include <com/sun/star/accessibility/AccessibleRole.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
25 #include <tools/debug.hxx>
26 #include <tools/gen.hxx>
27 #include <unotools/accessiblestatesethelper.hxx>
28 #include <toolkit/helper/convert.hxx>
29 #include <svl/smplhint.hxx>
30 #include <comphelper/sequence.hxx>
31 #include <comphelper/servicehelper.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <unotools/accessiblerelationsethelper.hxx>
34 #include <vcl/unohelp.hxx>
35 #include <comphelper/accessibleeventnotifier.hxx>
36 #include <vcl/svapp.hxx>
38 using namespace ::rtl
;
39 using namespace ::com::sun::star
;
40 using namespace ::com::sun::star::accessibility
;
42 ScAccessibleContextBase::ScAccessibleContextBase(
43 const uno::Reference
<XAccessible
>& rxParent
,
44 const sal_Int16 aRole
)
46 ScAccessibleContextBaseWeakImpl(m_aMutex
),
54 ScAccessibleContextBase::~ScAccessibleContextBase(void)
56 if (!IsDefunc() && !rBHelper
.bInDispose
)
58 // increment refcount to prevent double call off dtor
59 osl_atomic_increment( &m_refCount
);
60 // call dispose to inform object which have a weak reference to this object
65 void ScAccessibleContextBase::Init()
67 // hold reference to make sure that the destructor is not called
68 uno::Reference
< XAccessibleContext
> xOwnContext(this);
72 uno::Reference
< XAccessibleEventBroadcaster
> xBroadcaster (mxParent
->getAccessibleContext(), uno::UNO_QUERY
);
73 if (xBroadcaster
.is())
74 xBroadcaster
->addAccessibleEventListener(this);
76 msName
= createAccessibleName();
77 msDescription
= createAccessibleDescription();
80 void SAL_CALL
ScAccessibleContextBase::disposing()
82 SolarMutexGuard aGuard
;
83 // CommitDefunc(); not necessary and should not be send, because it cost a lot of time
85 // hold reference to make sure that the destructor is not called
86 uno::Reference
< XAccessibleContext
> xOwnContext(this);
90 sal_Int32
nTemClientId(mnClientId
);
92 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nTemClientId
, *this );
97 uno::Reference
< XAccessibleEventBroadcaster
> xBroadcaster (mxParent
->getAccessibleContext(), uno::UNO_QUERY
);
98 if (xBroadcaster
.is())
99 xBroadcaster
->removeAccessibleEventListener(this);
103 ScAccessibleContextBaseWeakImpl::disposing();
106 //===== XInterface =====================================================
108 uno::Any SAL_CALL
ScAccessibleContextBase::queryInterface( uno::Type
const & rType
)
109 throw (uno::RuntimeException
, std::exception
)
111 uno::Any
aAny (ScAccessibleContextBaseWeakImpl::queryInterface(rType
));
112 return aAny
.hasValue() ? aAny
: ScAccessibleContextBaseImplEvent::queryInterface(rType
);
115 void SAL_CALL
ScAccessibleContextBase::acquire()
118 ScAccessibleContextBaseWeakImpl::acquire();
121 void SAL_CALL
ScAccessibleContextBase::release()
124 ScAccessibleContextBaseWeakImpl::release();
127 //===== SfxListener =====================================================
129 void ScAccessibleContextBase::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
131 if (rHint
.ISA( SfxSimpleHint
) )
133 const SfxSimpleHint
& rRef
= (const SfxSimpleHint
&)rHint
;
134 if (rRef
.GetId() == SFX_HINT_DYING
)
136 // it seems the Broadcaster is dying, since the view is dying
142 //===== XAccessible =========================================================
144 uno::Reference
< XAccessibleContext
> SAL_CALL
145 ScAccessibleContextBase::getAccessibleContext(void)
146 throw (uno::RuntimeException
, std::exception
)
151 //===== XAccessibleComponent ================================================
153 sal_Bool SAL_CALL
ScAccessibleContextBase::containsPoint(const awt::Point
& rPoint
)
154 throw (uno::RuntimeException
, std::exception
)
156 SolarMutexGuard aGuard
;
158 return Rectangle (Point(), GetBoundingBox().GetSize()).IsInside(VCLPoint(rPoint
));
161 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleContextBase::getAccessibleAtPoint(
162 const awt::Point
& /* rPoint */ )
163 throw (uno::RuntimeException
, std::exception
)
165 OSL_FAIL("not implemented");
166 return uno::Reference
<XAccessible
>();
169 awt::Rectangle SAL_CALL
ScAccessibleContextBase::getBounds( )
170 throw (uno::RuntimeException
, std::exception
)
172 SolarMutexGuard aGuard
;
174 return AWTRectangle(GetBoundingBox());
177 awt::Point SAL_CALL
ScAccessibleContextBase::getLocation( )
178 throw (uno::RuntimeException
, std::exception
)
180 SolarMutexGuard aGuard
;
182 return AWTPoint(GetBoundingBox().TopLeft());
185 awt::Point SAL_CALL
ScAccessibleContextBase::getLocationOnScreen( )
186 throw (uno::RuntimeException
, std::exception
)
188 SolarMutexGuard aGuard
;
190 return AWTPoint(GetBoundingBoxOnScreen().TopLeft());
193 awt::Size SAL_CALL
ScAccessibleContextBase::getSize( )
194 throw (uno::RuntimeException
, std::exception
)
196 SolarMutexGuard aGuard
;
198 return AWTSize(GetBoundingBox().GetSize());
201 bool SAL_CALL
ScAccessibleContextBase::isShowing( )
202 throw (uno::RuntimeException
)
204 SolarMutexGuard aGuard
;
206 bool bShowing(false);
209 uno::Reference
<XAccessibleComponent
> xParentComponent (mxParent
->getAccessibleContext(), uno::UNO_QUERY
);
210 if (xParentComponent
.is())
212 Rectangle
aParentBounds(VCLRectangle(xParentComponent
->getBounds()));
213 Rectangle
aBounds(VCLRectangle(getBounds()));
214 bShowing
= aBounds
.IsOver(aParentBounds
);
220 bool SAL_CALL
ScAccessibleContextBase::isVisible()
221 throw (uno::RuntimeException
, std::exception
)
226 void SAL_CALL
ScAccessibleContextBase::grabFocus( )
227 throw (uno::RuntimeException
, std::exception
)
229 OSL_FAIL("not implemented");
232 sal_Int32 SAL_CALL
ScAccessibleContextBase::getForeground( )
233 throw (uno::RuntimeException
, std::exception
)
238 sal_Int32 SAL_CALL
ScAccessibleContextBase::getBackground( )
239 throw (uno::RuntimeException
, std::exception
)
244 //===== XAccessibleContext ==================================================
246 sal_Int32 SAL_CALL
ScAccessibleContextBase::getAccessibleChildCount()
247 throw (uno::RuntimeException
, std::exception
)
249 OSL_FAIL("should be implemented in the abrevated class");
253 uno::Reference
<XAccessible
> SAL_CALL
254 ScAccessibleContextBase::getAccessibleChild(sal_Int32
/* nIndex */)
255 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
,
258 OSL_FAIL("should be implemented in the abrevated class");
259 return uno::Reference
<XAccessible
>();
262 uno::Reference
<XAccessible
> SAL_CALL
263 ScAccessibleContextBase::getAccessibleParent(void)
264 throw (uno::RuntimeException
, std::exception
)
270 ScAccessibleContextBase::getAccessibleIndexInParent(void)
271 throw (uno::RuntimeException
, std::exception
)
273 SolarMutexGuard aGuard
;
275 // Use a simple but slow solution for now. Optimize later.
276 // Return -1 to indicate that this object's parent does not know about the
278 sal_Int32
nIndex(-1);
280 // Iterate over all the parent's children and search for this object.
283 uno::Reference
<XAccessibleContext
> xParentContext (
284 mxParent
->getAccessibleContext());
285 if (xParentContext
.is())
287 sal_Int32 nChildCount
= xParentContext
->getAccessibleChildCount();
288 for (sal_Int32 i
=0; i
<nChildCount
; ++i
)
290 uno::Reference
<XAccessible
> xChild (xParentContext
->getAccessibleChild (i
));
293 if (xChild
.get() == this)
304 ScAccessibleContextBase::getAccessibleRole(void)
305 throw (uno::RuntimeException
, std::exception
)
311 ScAccessibleContextBase::getAccessibleDescription(void)
312 throw (uno::RuntimeException
, std::exception
)
314 SolarMutexGuard aGuard
;
316 if (msDescription
.isEmpty())
318 OUString
sDescription(createAccessibleDescription());
320 if (msDescription
!= sDescription
)
322 AccessibleEventObject aEvent
;
323 aEvent
.EventId
= AccessibleEventId::DESCRIPTION_CHANGED
;
324 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
325 aEvent
.OldValue
<<= msDescription
;
326 aEvent
.NewValue
<<= sDescription
;
328 msDescription
= sDescription
;
330 CommitChange(aEvent
);
333 return msDescription
;
337 ScAccessibleContextBase::getAccessibleName(void)
338 throw (uno::RuntimeException
, std::exception
)
340 SolarMutexGuard aGuard
;
342 if (msName
.isEmpty())
344 OUString
sName(createAccessibleName());
345 OSL_ENSURE(!sName
.isEmpty(), "We should give always a name.");
349 AccessibleEventObject aEvent
;
350 aEvent
.EventId
= AccessibleEventId::NAME_CHANGED
;
351 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
352 aEvent
.OldValue
<<= msName
;
353 aEvent
.NewValue
<<= sName
;
357 CommitChange(aEvent
);
363 uno::Reference
<XAccessibleRelationSet
> SAL_CALL
364 ScAccessibleContextBase::getAccessibleRelationSet()
365 throw (uno::RuntimeException
, std::exception
)
367 return new utl::AccessibleRelationSetHelper();
370 uno::Reference
<XAccessibleStateSet
> SAL_CALL
371 ScAccessibleContextBase::getAccessibleStateSet(void)
372 throw (uno::RuntimeException
, std::exception
)
374 return uno::Reference
<XAccessibleStateSet
>();
377 lang::Locale SAL_CALL
378 ScAccessibleContextBase::getLocale(void)
379 throw (IllegalAccessibleComponentStateException
,
380 uno::RuntimeException
, std::exception
)
382 SolarMutexGuard aGuard
;
386 uno::Reference
<XAccessibleContext
> xParentContext (
387 mxParent
->getAccessibleContext());
388 if (xParentContext
.is())
389 return xParentContext
->getLocale ();
392 // No locale and no parent. Therefore throw exception to indicate this
394 throw IllegalAccessibleComponentStateException ();
397 //===== XAccessibleEventBroadcaster =====================================
400 ScAccessibleContextBase::addAccessibleEventListener(
401 const uno::Reference
<XAccessibleEventListener
>& xListener
)
402 throw (uno::RuntimeException
, std::exception
)
406 SolarMutexGuard aGuard
;
411 mnClientId
= comphelper::AccessibleEventNotifier::registerClient( );
412 comphelper::AccessibleEventNotifier::addEventListener( mnClientId
, xListener
);
418 ScAccessibleContextBase::removeAccessibleEventListener(
419 const uno::Reference
<XAccessibleEventListener
>& xListener
)
420 throw (uno::RuntimeException
, std::exception
)
424 SolarMutexGuard aGuard
;
425 if (!IsDefunc() && mnClientId
)
427 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( mnClientId
, xListener
);
428 if ( !nListenerCount
)
430 // no listeners anymore
431 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
432 // and at least to us not firing any events anymore, in case somebody calls
433 // NotifyAccessibleEvent, again
434 comphelper::AccessibleEventNotifier::revokeClient( mnClientId
);
441 //===== XAccessibleEventListener ========================================
443 void SAL_CALL
ScAccessibleContextBase::disposing(
444 const lang::EventObject
& rSource
)
445 throw (uno::RuntimeException
, std::exception
)
447 SolarMutexGuard aGuard
;
448 if (rSource
.Source
== mxParent
)
452 void SAL_CALL
ScAccessibleContextBase::notifyEvent(
453 const AccessibleEventObject
& /* aEvent */ )
454 throw (uno::RuntimeException
, std::exception
)
458 //===== XServiceInfo ========================================================
459 OUString SAL_CALL
ScAccessibleContextBase::getImplementationName(void)
460 throw (uno::RuntimeException
, std::exception
)
462 return OUString("ScAccessibleContextBase");
465 sal_Bool SAL_CALL
ScAccessibleContextBase::supportsService(const OUString
& sServiceName
)
466 throw (uno::RuntimeException
, std::exception
)
468 return cppu::supportsService(this, sServiceName
);
471 uno::Sequence
< OUString
> SAL_CALL
472 ScAccessibleContextBase::getSupportedServiceNames(void)
473 throw (uno::RuntimeException
, std::exception
)
475 uno::Sequence
<OUString
> aServiceNames(2);
476 OUString
* pServiceNames
= aServiceNames
.getArray();
479 pServiceNames
[0] = "com.sun.star.accessibility.Accessible";
480 pServiceNames
[1] = "com.sun.star.accessibility.AccessibleContext";
483 return aServiceNames
;
486 //===== XTypeProvider =======================================================
488 uno::Sequence
< uno::Type
> SAL_CALL
ScAccessibleContextBase::getTypes()
489 throw (uno::RuntimeException
, std::exception
)
491 return comphelper::concatSequences(ScAccessibleContextBaseWeakImpl::getTypes(), ScAccessibleContextBaseImplEvent::getTypes());
494 uno::Sequence
<sal_Int8
> SAL_CALL
495 ScAccessibleContextBase::getImplementationId(void)
496 throw (uno::RuntimeException
, std::exception
)
498 return css::uno::Sequence
<sal_Int8
>();
501 //===== internal ============================================================
504 ScAccessibleContextBase::createAccessibleDescription(void)
505 throw (uno::RuntimeException
)
507 OSL_FAIL("should be implemented in the abrevated class");
511 OUString SAL_CALL
ScAccessibleContextBase::createAccessibleName()
512 throw (uno::RuntimeException
, std::exception
)
514 OSL_FAIL("should be implemented in the abrevated class");
518 void ScAccessibleContextBase::CommitChange(const AccessibleEventObject
& rEvent
) const
521 comphelper::AccessibleEventNotifier::addEvent( mnClientId
, rEvent
);
524 void ScAccessibleContextBase::CommitFocusGained() const
526 AccessibleEventObject aEvent
;
527 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
528 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(const_cast<ScAccessibleContextBase
*>(this));
529 aEvent
.NewValue
<<= AccessibleStateType::FOCUSED
;
531 CommitChange(aEvent
);
533 ::vcl::unohelper::NotifyAccessibleStateEventGlobally(aEvent
);
536 void ScAccessibleContextBase::CommitFocusLost() const
538 AccessibleEventObject aEvent
;
539 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
540 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(const_cast<ScAccessibleContextBase
*>(this));
541 aEvent
.OldValue
<<= AccessibleStateType::FOCUSED
;
543 CommitChange(aEvent
);
545 vcl::unohelper::NotifyAccessibleStateEventGlobally(aEvent
);
548 Rectangle
ScAccessibleContextBase::GetBoundingBoxOnScreen() const
549 throw (uno::RuntimeException
, std::exception
)
551 OSL_FAIL("not implemented");
555 Rectangle
ScAccessibleContextBase::GetBoundingBox() const
556 throw (uno::RuntimeException
, std::exception
)
558 OSL_FAIL("not implemented");
562 void ScAccessibleContextBase::IsObjectValid() const
563 throw (lang::DisposedException
)
565 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
566 throw lang::DisposedException();
569 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */