LibreOffice Module sc (master)  1
AccessibleContextBase.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <AccessibleContextBase.hxx>
21 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
22 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
23 #include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
24 #include <tools/gen.hxx>
25 #include <tools/color.hxx>
27 #include <svl/hint.hxx>
28 #include <comphelper/sequence.hxx>
31 #include <vcl/unohelp.hxx>
33 #include <vcl/svapp.hxx>
34 
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::accessibility;
37 
39  const uno::Reference<XAccessible>& rxParent,
40  const sal_Int16 aRole)
41  :
43  mxParent(rxParent),
44  mnClientId(0),
45  maRole(aRole)
46 {
47 }
48 
50 {
51  if (!IsDefunc() && !rBHelper.bInDispose)
52  {
53  // increment refcount to prevent double call off dtor
54  osl_atomic_increment( &m_refCount );
55  // call dispose to inform object which have a weak reference to this object
56  dispose();
57  }
58 }
59 
61 {
62  // hold reference to make sure that the destructor is not called
63  uno::Reference< XAccessibleContext > xKeepAlive(this);
64 
65  if (mxParent.is())
66  {
67  uno::Reference< XAccessibleEventBroadcaster > xBroadcaster (mxParent->getAccessibleContext(), uno::UNO_QUERY);
68  if (xBroadcaster.is())
69  xBroadcaster->addAccessibleEventListener(this);
70  }
73 }
74 
76 {
77  SolarMutexGuard aGuard;
78 // CommitDefunc(); not necessary and should not be send, because it cost a lot of time
79 
80  // hold reference to make sure that the destructor is not called
81  uno::Reference< XAccessibleContext > xKeepAlive(this);
82 
83  if ( mnClientId )
84  {
85  sal_Int32 nTemClientId(mnClientId);
86  mnClientId = 0;
88  }
89 
90  if (mxParent.is())
91  {
92  uno::Reference< XAccessibleEventBroadcaster > xBroadcaster (mxParent->getAccessibleContext(), uno::UNO_QUERY);
93  if (xBroadcaster.is())
94  xBroadcaster->removeAccessibleEventListener(this);
95  mxParent = nullptr;
96  }
97 
98  ScAccessibleContextBaseWeakImpl::disposing();
99 }
100 
101 //===== XInterface =====================================================
102 
104 {
106  return aAny.hasValue() ? aAny : ScAccessibleContextBaseImplEvent::queryInterface(rType);
107 }
108 
110  throw ()
111 {
113 }
114 
116  throw ()
117 {
119 }
120 
121 //===== SfxListener =====================================================
122 
124 {
125  if (rHint.GetId() == SfxHintId::Dying)
126  {
127  // it seems the Broadcaster is dying, since the view is dying
128  dispose();
129  }
130 }
131 
132 //===== XAccessible =========================================================
133 
134 uno::Reference< XAccessibleContext> SAL_CALL
136 {
137  return this;
138 }
139 
140 //===== XAccessibleComponent ================================================
141 
142 sal_Bool SAL_CALL ScAccessibleContextBase::containsPoint(const awt::Point& rPoint )
143 {
144  SolarMutexGuard aGuard;
145  IsObjectValid();
146  return tools::Rectangle (Point(), GetBoundingBox().GetSize()).IsInside(VCLPoint(rPoint));
147 }
148 
149 uno::Reference< XAccessible > SAL_CALL ScAccessibleContextBase::getAccessibleAtPoint(
150  const awt::Point& /* rPoint */ )
151 {
152  OSL_FAIL("not implemented");
153  return uno::Reference<XAccessible>();
154 }
155 
156 awt::Rectangle SAL_CALL ScAccessibleContextBase::getBounds( )
157 {
158  SolarMutexGuard aGuard;
159  IsObjectValid();
160  return AWTRectangle(GetBoundingBox());
161 }
162 
164 {
165  SolarMutexGuard aGuard;
166  IsObjectValid();
167  return AWTPoint(GetBoundingBox().TopLeft());
168 }
169 
171 {
172  SolarMutexGuard aGuard;
173  IsObjectValid();
175 }
176 
177 awt::Size SAL_CALL ScAccessibleContextBase::getSize( )
178 {
179  SolarMutexGuard aGuard;
180  IsObjectValid();
181  return AWTSize(GetBoundingBox().GetSize());
182 }
183 
185 {
186  SolarMutexGuard aGuard;
187  IsObjectValid();
188  bool bShowing(false);
189  if (mxParent.is())
190  {
191  uno::Reference<XAccessibleComponent> xParentComponent (mxParent->getAccessibleContext(), uno::UNO_QUERY);
192  if (xParentComponent.is())
193  {
194  tools::Rectangle aParentBounds(VCLRectangle(xParentComponent->getBounds()));
196  bShowing = aBounds.IsOver(aParentBounds);
197  }
198  }
199  return bShowing;
200 }
201 
203 {
204  return true;
205 }
206 
208 {
209  OSL_FAIL("not implemented");
210 }
211 
213 {
214  return sal_Int32(COL_BLACK);
215 }
216 
218 {
219  return sal_Int32(COL_WHITE);
220 }
221 
222 //===== XAccessibleContext ==================================================
223 
225 {
226  OSL_FAIL("should be implemented in the abrevated class");
227  return 0;
228 }
229 
230 uno::Reference<XAccessible> SAL_CALL
232 {
233  OSL_FAIL("should be implemented in the abrevated class");
234  return uno::Reference<XAccessible>();
235 }
236 
237 uno::Reference<XAccessible> SAL_CALL
239 {
240  return mxParent;
241 }
242 
243 sal_Int32 SAL_CALL
245 {
246  SolarMutexGuard aGuard;
247  IsObjectValid();
248  // Use a simple but slow solution for now. Optimize later.
249  // Return -1 to indicate that this object's parent does not know about the
250  // object.
251  sal_Int32 nIndex(-1);
252 
253  // Iterate over all the parent's children and search for this object.
254  if (mxParent.is())
255  {
256  uno::Reference<XAccessibleContext> xParentContext (
257  mxParent->getAccessibleContext());
258  if (xParentContext.is())
259  {
260  sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
261  for (sal_Int32 i=0; i<nChildCount; ++i)
262  {
263  uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i));
264  if (xChild.is() && xChild.get() == this)
265  nIndex = i;
266  }
267  }
268  }
269 
270  return nIndex;
271 }
272 
273 sal_Int16 SAL_CALL
275 {
276  return maRole;
277 }
278 
279 OUString SAL_CALL
281 {
282  SolarMutexGuard aGuard;
283  IsObjectValid();
284  if (msDescription.isEmpty())
285  {
286  OUString sDescription(createAccessibleDescription());
287 
288  if (msDescription != sDescription)
289  {
290  AccessibleEventObject aEvent;
291  aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
292  aEvent.Source = uno::Reference< XAccessibleContext >(this);
293  aEvent.OldValue <<= msDescription;
294  aEvent.NewValue <<= sDescription;
295 
296  msDescription = sDescription;
297 
298  CommitChange(aEvent);
299  }
300  }
301  return msDescription;
302 }
303 
304 OUString SAL_CALL
306 {
307  SolarMutexGuard aGuard;
308  IsObjectValid();
309  if (msName.isEmpty())
310  {
311  OUString sName(createAccessibleName());
312  OSL_ENSURE(!sName.isEmpty(), "We should give always a name.");
313 
314  if (msName != sName)
315  {
316  AccessibleEventObject aEvent;
317  aEvent.EventId = AccessibleEventId::NAME_CHANGED;
318  aEvent.Source = uno::Reference< XAccessibleContext >(this);
319  aEvent.OldValue <<= msName;
320  aEvent.NewValue <<= sName;
321 
322  msName = sName;
323 
324  CommitChange(aEvent);
325  }
326  }
327  return msName;
328 }
329 
330 uno::Reference<XAccessibleRelationSet> SAL_CALL
332 {
334 }
335 
336 uno::Reference<XAccessibleStateSet> SAL_CALL
338 {
339  return uno::Reference<XAccessibleStateSet>();
340 }
341 
342 lang::Locale SAL_CALL
344 {
345  SolarMutexGuard aGuard;
346  IsObjectValid();
347  if (mxParent.is())
348  {
349  uno::Reference<XAccessibleContext> xParentContext (
350  mxParent->getAccessibleContext());
351  if (xParentContext.is())
352  return xParentContext->getLocale ();
353  }
354 
355  // No locale and no parent. Therefore throw exception to indicate this
356  // cluelessness.
357  throw IllegalAccessibleComponentStateException ();
358 }
359 
360  //===== XAccessibleEventBroadcaster =====================================
361 
362 void SAL_CALL
364  const uno::Reference<XAccessibleEventListener>& xListener)
365 {
366  if (xListener.is())
367  {
368  SolarMutexGuard aGuard;
369  IsObjectValid();
370  if (!IsDefunc())
371  {
372  if (!mnClientId)
375  }
376  }
377 }
378 
379 void SAL_CALL
381  const uno::Reference<XAccessibleEventListener>& xListener)
382 {
383  if (!xListener.is())
384  return;
385 
386  SolarMutexGuard aGuard;
387  if (IsDefunc() || !mnClientId)
388  return;
389 
390  sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, xListener );
391  if ( !nListenerCount )
392  {
393  // no listeners anymore
394  // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
395  // and at least to us not firing any events anymore, in case somebody calls
396  // NotifyAccessibleEvent, again
398  mnClientId = 0;
399  }
400 }
401 
402  //===== XAccessibleEventListener ========================================
403 
405  const lang::EventObject& rSource )
406 {
407  SolarMutexGuard aGuard;
408  if (rSource.Source == mxParent)
409  dispose();
410 }
411 
413  const AccessibleEventObject& /* aEvent */ )
414 {
415 }
416 
417 // XServiceInfo
419 {
420  return "ScAccessibleContextBase";
421 }
422 
423 sal_Bool SAL_CALL ScAccessibleContextBase::supportsService(const OUString& sServiceName)
424 {
425  return cppu::supportsService(this, sServiceName);
426 }
427 
428 uno::Sequence< OUString> SAL_CALL
430 {
431  return {"com.sun.star.accessibility.Accessible",
432  "com.sun.star.accessibility.AccessibleContext"};
433 }
434 
435 //===== XTypeProvider =======================================================
436 
437 uno::Sequence< uno::Type > SAL_CALL ScAccessibleContextBase::getTypes()
438 {
440 }
441 
442 uno::Sequence<sal_Int8> SAL_CALL
444 {
445  return css::uno::Sequence<sal_Int8>();
446 }
447 
448 //===== internal ============================================================
449 
450 OUString
452 {
453  OSL_FAIL("should be implemented in the abrevated class");
454  return OUString();
455 }
456 
458 {
459  OSL_FAIL("should be implemented in the abrevated class");
460  return OUString();
461 }
462 
463 void ScAccessibleContextBase::CommitChange(const AccessibleEventObject& rEvent) const
464 {
465  if (mnClientId)
467 }
468 
470 {
471  AccessibleEventObject aEvent;
472  aEvent.EventId = AccessibleEventId::STATE_CHANGED;
473  aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
474  aEvent.NewValue <<= AccessibleStateType::FOCUSED;
475 
476  CommitChange(aEvent);
477 
479 }
480 
482 {
483  AccessibleEventObject aEvent;
484  aEvent.EventId = AccessibleEventId::STATE_CHANGED;
485  aEvent.Source = uno::Reference< XAccessibleContext >(const_cast<ScAccessibleContextBase*>(this));
486  aEvent.OldValue <<= AccessibleStateType::FOCUSED;
487 
488  CommitChange(aEvent);
489 
491 }
492 
494 {
495  OSL_FAIL("not implemented");
496  return tools::Rectangle();
497 }
498 
500 {
501  OSL_FAIL("not implemented");
502  return tools::Rectangle();
503 }
504 
506 {
507  if (rBHelper.bDisposed || rBHelper.bInDispose)
508  throw lang::DisposedException();
509 }
510 
511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::lang::Locale SAL_CALL getLocale() override
Return the parents locale or throw exception if this object has no parent yet/anymore.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
Return the specified child or NULL if index is invalid.
OUString msDescription
Description of this object.
bool hasValue()
sal_Int32 nIndex
css::awt::Point AWTPoint(const ::Point &rVCLPoint)
sal_Int16 maRole
This is the role of this object.
osl::Mutex m_aMutex
virtual void SAL_CALL acquire() SAL_OVERRIDE
ScAccessibleContextBase(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, const sal_Int16 aRole)
ULONG m_refCount
WeakReference< XInterface > mxParent
bool IsOver(const tools::Rectangle &rRect) const
virtual tools::Rectangle GetBoundingBox() const
Return the object's current bounding box relative to the parent object.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override
Return the set of current states.
virtual OUString SAL_CALL getAccessibleName() override
Return the object's current name.
virtual void SAL_CALL release() override
virtual void SAL_CALL grabFocus() override
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ====================================================
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
Return NULL to indicate that an empty relation set.
SfxHintId GetId() const
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
===== XAccessibleContext ==============================================
virtual void SAL_CALL removeAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
virtual css::awt::Point SAL_CALL getLocation() override
virtual OUString SAL_CALL getAccessibleDescription() override
Return this object's description.
css::awt::Size AWTSize(const Size &rVCLSize)
virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override
Return this objects index among the parents children.
virtual OUString createAccessibleName()
Return the object's current name.
virtual css::awt::Rectangle SAL_CALL getBounds() override
virtual OUString createAccessibleDescription()
Return this object's description.
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
const char * sName
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual void SAL_CALL notifyEvent(const css::accessibility::AccessibleEventObject &aEvent) override
virtual void SAL_CALL addAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &xListener) override
===== XAccessibleEventBroadcaster =====================================
int i
virtual css::awt::Size SAL_CALL getSize() override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
===== XTypeProvider ===================================================
OUString msName
Name of this object.
virtual sal_Int16 SAL_CALL getAccessibleRole() override
Return this object's role.
virtual css::awt::Point SAL_CALL getLocationOnScreen() override
inline::tools::Rectangle VCLRectangle(const css::awt::Rectangle &rAWTRect)
static sal_Int32 removeEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
unsigned char sal_Bool
void CommitFocusGained() const
Calls all FocusListener to tell they that the focus is gained.
bool IsInside(const Point &rPOINT) const
inline::Point VCLPoint(const css::awt::Point &rAWTPoint)
virtual sal_Int32 SAL_CALL getBackground() override
virtual void SAL_CALL acquire() override
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &...rSn)
static void revokeClientNotifyDisposing(const TClientId _nClient, const css::uno::Reference< css::uno::XInterface > &_rxEventSource)
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Returns an implementation id.
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual tools::Rectangle GetBoundingBoxOnScreen() const
Return the object's current bounding box relative to the desktop.
sal_uInt32 mnClientId
client id in the AccessibleEventNotifier queue
virtual void SAL_CALL disposing() override
static void revokeClient(const TClientId _nClient)
virtual void SAL_CALL release() SAL_OVERRIDE
virtual sal_Bool SAL_CALL supportsService(const OUString &sServiceName) override
Return whether the specified service is supported by this class.
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
void CommitFocusLost() const
Calls all FocusListener to tell they that the focus is lost.
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
css::uno::Reference< css::accessibility::XAccessible > mxParent
Reference to the parent object.
virtual sal_Int32 SAL_CALL getForeground() override
void CommitChange(const css::accessibility::AccessibleEventObject &rEvent) const
Calls all Listener to tell they the change.
virtual ~ScAccessibleContextBase() override
static void addEvent(const TClientId _nClient, const css::accessibility::AccessibleEventObject &_rEvent)
void dispose()
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
VCL_DLLPUBLIC void NotifyAccessibleStateEventGlobally(const css::accessibility::AccessibleEventObject &rEventObject)
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
AnyEventRef aEvent
css::awt::Rectangle AWTRectangle(const ::tools::Rectangle &rVCLRect)
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
static sal_Int32 addEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================