LibreOffice Module accessibility (master) 1
AccessibleBrowseBoxBase.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
22#include <utility>
25
26#include <com/sun/star/accessibility/AccessibleEventId.hpp>
27#include <com/sun/star/accessibility/AccessibleRole.hpp>
28#include <com/sun/star/accessibility/AccessibleStateType.hpp>
29#include <com/sun/star/accessibility/IllegalAccessibleComponentStateException.hpp>
31#include <vcl/window.hxx>
32#include <vcl/svapp.hxx>
33#include <sal/log.hxx>
34
35
36using ::com::sun::star::uno::Reference;
37using ::com::sun::star::uno::Sequence;
38using ::com::sun::star::uno::Any;
39
40using namespace ::com::sun::star;
41using namespace ::com::sun::star::accessibility;
42using namespace ::comphelper;
43
44
45namespace accessibility {
46
47using namespace com::sun::star::accessibility::AccessibleStateType;
48
49
50// Ctor/Dtor/disposing
51
53 css::uno::Reference< css::accessibility::XAccessible > xParent,
55 css::uno::Reference< css::awt::XWindow > _xFocusWindow,
58 mxParent(std::move( xParent )),
59 mpBrowseBox( &rBrowseBox ),
60 m_xFocusWindow(std::move(_xFocusWindow)),
61 maName( rBrowseBox.GetAccessibleObjectName( eObjType ) ),
62 maDescription( rBrowseBox.GetAccessibleObjectDescription( eObjType ) ),
63 meObjType( eObjType ),
64 m_aClientId(0)
65{
66 if ( m_xFocusWindow.is() )
67 m_xFocusWindow->addFocusListener( this );
68}
69
71 css::uno::Reference< css::accessibility::XAccessible > rxParent,
73 css::uno::Reference< css::awt::XWindow > _xFocusWindow,
75 OUString rName,
76 OUString rDescription ) :
78 mxParent(std::move( rxParent )),
79 mpBrowseBox( &rBrowseBox ),
80 m_xFocusWindow(std::move(_xFocusWindow)),
81 maName(std::move( rName )),
82 maDescription(std::move( rDescription )),
83 meObjType( eObjType ),
84 m_aClientId(0)
85{
86 if ( m_xFocusWindow.is() )
87 m_xFocusWindow->addFocusListener( this );
88}
89
91{
92 if( isAlive() )
93 {
94 // increment ref count to prevent double call of Dtor
95 osl_atomic_increment( &m_refCount );
96 dispose();
97 }
98}
99
101{
102 ::osl::MutexGuard aGuard( getMutex() );
103 if ( m_xFocusWindow.is() )
104 {
105 SolarMutexGuard aSolarGuard;
106 m_xFocusWindow->removeFocusListener( this );
107 }
108
109 if ( getClientId( ) )
110 {
112 setClientId( 0 );
114 }
115
116 mxParent = nullptr;
117 mpBrowseBox = nullptr;
118}
119
120// css::accessibility::XAccessibleContext
121
123{
124 ::osl::MutexGuard aGuard( getMutex() );
126 return mxParent;
127}
128
130{
131 ::osl::MutexGuard aGuard( getMutex() );
133
134 // -1 for child not found/no parent (according to specification)
135 sal_Int64 nRet = -1;
136
137 css::uno::Reference< uno::XInterface > xMeMyselfAndI( static_cast< css::accessibility::XAccessibleContext* >( this ), uno::UNO_QUERY );
138
139 // iterate over parent's children and search for this object
140 if( mxParent.is() )
141 {
142 css::uno::Reference< css::accessibility::XAccessibleContext >
143 xParentContext( mxParent->getAccessibleContext() );
144 if( xParentContext.is() )
145 {
146 css::uno::Reference< uno::XInterface > xChild;
147
148 sal_Int64 nChildCount = xParentContext->getAccessibleChildCount();
149 for( sal_Int64 nChild = 0; nChild < nChildCount; ++nChild )
150 {
151 xChild.set(xParentContext->getAccessibleChild( nChild ), css::uno::UNO_QUERY);
152
153 if ( xMeMyselfAndI.get() == xChild.get() )
154 {
155 nRet = nChild;
156 break;
157 }
158 }
159 }
160 }
161 return nRet;
162}
163
165{
166 ::osl::MutexGuard aGuard( getMutex() );
168 return maDescription;
169}
172{
173 ::osl::MutexGuard aGuard( getMutex() );
175 return maName;
176}
177
180{
181 ::osl::MutexGuard aGuard( getMutex() );
183 // BrowseBox does not have relations.
185}
186
187sal_Int64 SAL_CALL
189{
190 SolarMethodGuard aGuard( getMutex() );
191 // don't check whether alive -> StateSet may contain DEFUNC
192 return implCreateStateSet();
193}
194
196{
197 ::osl::MutexGuard aGuard( getMutex() );
199 if( mxParent.is() )
200 {
201 css::uno::Reference< css::accessibility::XAccessibleContext >
202 xParentContext( mxParent->getAccessibleContext() );
203 if( xParentContext.is() )
204 return xParentContext->getLocale();
205 }
206 throw IllegalAccessibleComponentStateException();
207}
208
209// css::accessibility::XAccessibleComponent
210
211sal_Bool SAL_CALL AccessibleBrowseBoxBase::containsPoint( const css::awt::Point& rPoint )
212{
213 return tools::Rectangle( Point(), getBoundingBox().GetSize() ).Contains( VCLPoint( rPoint ) );
214}
215
216awt::Rectangle SAL_CALL AccessibleBrowseBoxBase::getBounds()
217{
218 return AWTRectangle( getBoundingBox() );
219}
220
222{
223 return AWTPoint( getBoundingBox().TopLeft() );
224}
225
227{
229}
230
232{
233 return AWTSize( getBoundingBox().GetSize() );
234}
235
236void SAL_CALL AccessibleBrowseBoxBase::focusGained( const css::awt::FocusEvent& )
237{
238 com::sun::star::uno::Any aFocused;
239 com::sun::star::uno::Any aEmpty;
240 aFocused <<= FOCUSED;
241
242 commitEvent(AccessibleEventId::STATE_CHANGED,aFocused,aEmpty);
243}
244
245
246void SAL_CALL AccessibleBrowseBoxBase::focusLost( const css::awt::FocusEvent& )
247{
248 com::sun::star::uno::Any aFocused;
249 com::sun::star::uno::Any aEmpty;
250 aFocused <<= FOCUSED;
251
252 commitEvent(AccessibleEventId::STATE_CHANGED,aEmpty,aFocused);
253}
254// css::accessibility::XAccessibleEventBroadcaster
255
257 const css::uno::Reference< css::accessibility::XAccessibleEventListener>& _rxListener )
258{
259 if ( _rxListener.is() )
260 {
261 ::osl::MutexGuard aGuard( getMutex() );
262 if ( !getClientId( ) )
264
266 }
267}
268
270 const css::uno::Reference< css::accessibility::XAccessibleEventListener>& _rxListener )
271{
272 if( !(_rxListener.is() && getClientId( )) )
273 return;
274
275 ::osl::MutexGuard aGuard( getMutex() );
276 sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener );
277 if ( !nListenerCount )
278 {
279 // no listeners anymore
280 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
281 // and at least to us not firing any events anymore, in case somebody calls
282 // NotifyAccessibleEvent, again
283
285 setClientId( 0 );
287 }
288}
289
290// XTypeProvider
291
293{
294 return css::uno::Sequence<sal_Int8>();
295}
296
297// XServiceInfo
298
300 const OUString& rServiceName )
301{
302 return cppu::supportsService(this, rServiceName);
303}
304
306{
307 return { "com.sun.star.accessibility.AccessibleContext" };
308}
309
310// other public methods
311
313{
314 ::osl::ClearableMutexGuard aGuard( getMutex() );
315 Any aOld;
316 aOld <<= maName;
317 maName = rName;
318
319 aGuard.clear();
320
322 AccessibleEventId::NAME_CHANGED,
323 uno::Any( maName ),
324 aOld );
325}
326
327void AccessibleBrowseBoxBase::setAccessibleDescription( const OUString& rDescription )
328{
329 ::osl::ClearableMutexGuard aGuard( getMutex() );
330 Any aOld;
331 aOld <<= maDescription;
332 maDescription = rDescription;
333
334 aGuard.clear();
335
337 AccessibleEventId::DESCRIPTION_CHANGED,
339 aOld );
340}
341
342// internal virtual methods
343
345{
346 bool bShowing = false;
347 if( mxParent.is() )
348 {
349 css::uno::Reference< css::accessibility::XAccessibleComponent >
350 xParentComp( mxParent->getAccessibleContext(), uno::UNO_QUERY );
351 if( xParentComp.is() )
352 bShowing = implGetBoundingBox().Overlaps(
353 VCLRectangle( xParentComp->getBounds() ) );
354 }
355 return bShowing;
356}
357
359{
360 sal_Int64 nStateSet = 0;
361
362 if( isAlive() )
363 {
364 // SHOWING done with mxParent
365 if( implIsShowing() )
366 nStateSet |= AccessibleStateType::SHOWING;
367 // BrowseBox fills StateSet with states depending on object type
369 }
370 else
371 nStateSet |= AccessibleStateType::DEFUNC;
372
373 return nStateSet;
374}
375
376// internal helper methods
377
379{
380 return !rBHelper.bDisposed && !rBHelper.bInDispose && mpBrowseBox;
381}
382
384{
385 if( !isAlive() )
386 throw lang::DisposedException();
387}
388
390{
391 SolarMethodGuard aGuard(getMutex());
393
395 if ( aRect.Left() == 0 && aRect.Top() == 0 && aRect.Right() == 0 && aRect.Bottom() == 0 )
396 {
397 SAL_WARN( "accessibility", "rectangle doesn't exist" );
398 }
399 return aRect;
400}
401
403{
404 SolarMethodGuard aGuard(getMutex());
406
408 if ( aRect.Left() == 0 && aRect.Top() == 0 && aRect.Right() == 0 && aRect.Bottom() == 0 )
409 {
410 SAL_WARN( "accessibility", "rectangle doesn't exist" );
411 }
412 return aRect;
413}
414
416 sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
417{
418 osl::MutexGuard aGuard( getMutex() );
419 if ( !getClientId( ) )
420 // if we don't have a client id for the notifier, then we don't have listeners, then
421 // we don't need to notify anything
422 return;
423
424 // build an event object
425 AccessibleEventObject aEvent(*this, _nEventId, _rNewValue, _rOldValue, -1);
426
427 // let the notifier handle this event
428
430}
431
433{
434 osl::MutexGuard aGuard( getMutex() );
436 sal_Int16 nRole = AccessibleRole::UNKNOWN;
437 switch ( meObjType )
438 {
439 case AccessibleBrowseBoxObjType::RowHeaderCell:
440 nRole = AccessibleRole::ROW_HEADER;
441 break;
442 case AccessibleBrowseBoxObjType::ColumnHeaderCell:
443 nRole = AccessibleRole::COLUMN_HEADER;
444 break;
445 case AccessibleBrowseBoxObjType::ColumnHeaderBar:
446 case AccessibleBrowseBoxObjType::RowHeaderBar:
447 case AccessibleBrowseBoxObjType::Table:
448 nRole = AccessibleRole::TABLE;
449 break;
450 case AccessibleBrowseBoxObjType::TableCell:
451 nRole = AccessibleRole::TABLE_CELL;
452 break;
453 case AccessibleBrowseBoxObjType::BrowseBox:
454 nRole = AccessibleRole::PANEL;
455 break;
456 case AccessibleBrowseBoxObjType::CheckBoxCell:
457 nRole = AccessibleRole::CHECK_BOX;
458 break;
459 }
460 return nRole;
461}
462
464{
465 return nullptr;
466}
467
468void SAL_CALL AccessibleBrowseBoxBase::disposing( const css::lang::EventObject& )
469{
470 m_xFocusWindow = nullptr;
471}
472
474{
475 SolarMethodGuard aGuard(getMutex());
477
478 Color nColor;
480 if ( pInst )
481 {
482 if ( pInst->IsControlForeground() )
483 nColor = pInst->GetControlForeground();
484 else
485 {
486 vcl::Font aFont;
487 if ( pInst->IsControlFont() )
488 aFont = pInst->GetControlFont();
489 else
490 aFont = pInst->GetFont();
491 nColor = aFont.GetColor();
492 }
493 }
494
495 return sal_Int32(nColor);
496}
497
499{
500 SolarMethodGuard aGuard(getMutex());
502
503 Color nColor;
505 if ( pInst )
506 {
507 if ( pInst->IsControlBackground() )
508 nColor = pInst->GetControlBackground();
509 else
510 nColor = pInst->GetBackground().GetColor();
511 }
512
513 return sal_Int32(nColor);
514}
515
516
517// XInterface
519
520// XTypeProvider
522
523// css::accessibility::XAccessible
524
525Reference< css::accessibility::XAccessibleContext > SAL_CALL BrowseBoxAccessibleElement::getAccessibleContext()
526{
527 osl::MutexGuard aGuard( getMutex() );
528 ensureIsAlive();
529 return this;
530}
531
532
533BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const css::uno::Reference< css::accessibility::XAccessible >& rxParent, ::vcl::IAccessibleTableProvider& rBrowseBox,
534 const css::uno::Reference< css::awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType eObjType )
535 :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType )
536{
537}
538
539
540BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const css::uno::Reference< css::accessibility::XAccessible >& rxParent, ::vcl::IAccessibleTableProvider& rBrowseBox,
541 const css::uno::Reference< css::awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType eObjType,
542 const OUString& rName, const OUString& rDescription )
543 :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType, rName, rDescription )
544{
545}
546
547
549{
550}
551
552
553} // namespace accessibility
554
555
556/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AccessibleBrowseBoxObjType
unotools::WeakReference< AnimationNode > mxParent
AnyEventRef aEvent
OUString maName
const Color & GetColor() const
The BrowseBox accessible objects inherit from this base class.
virtual tools::Rectangle implGetBoundingBox()=0
Derived classes return the bounding box relative to the parent window.
::vcl::IAccessibleTableProvider * mpBrowseBox
The VCL BrowseBox control.
virtual sal_Int64 SAL_CALL getAccessibleIndexInParent() override
virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
void setAccessibleDescription(const OUString &rDescription)
Changes the description of the object and notifies listeners.
void setAccessibleName(const OUString &rName)
Changes the name of the object and notifies listeners.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
css::uno::Reference< css::awt::XWindow > m_xFocusWindow
This is the window which get all the nice focus events.
virtual OUString SAL_CALL getAccessibleDescription() override
virtual css::awt::Point SAL_CALL getLocation() override
void setClientId(::comphelper::AccessibleEventNotifier::TClientId _aNewClientId)
::comphelper::AccessibleEventNotifier::TClientId getClientId() const
virtual css::awt::Rectangle SAL_CALL getBounds() override
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
AccessibleBrowseBoxObjType meObjType
The type of this object (for names, descriptions, state sets, ...).
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
virtual sal_Int16 SAL_CALL getAccessibleRole() override
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
virtual css::awt::Size SAL_CALL getSize() override
virtual tools::Rectangle implGetBoundingBoxOnScreen()=0
Derived classes return the bounding box in screen coordinates.
tools::Rectangle getBoundingBoxOnScreen()
Locks all mutex's and calculates the bounding box in screen coordinates.
AccessibleBrowseBoxBase(css::uno::Reference< css::accessibility::XAccessible > xParent, ::vcl::IAccessibleTableProvider &rBrowseBox, css::uno::Reference< css::awt::XWindow > _xFocusWindow, AccessibleBrowseBoxObjType eObjType)
Constructor sets specified name and description.
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual sal_Int64 implCreateStateSet()
Creates a bitset of states of the current object.
AccessibleBrowseBoxObjType getType() const
OUString maDescription
Localized description text.
virtual sal_Int32 SAL_CALL getBackground() override
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
virtual OUString SAL_CALL getAccessibleName() override
virtual sal_Int32 SAL_CALL getForeground() override
virtual void SAL_CALL disposing() override
Commits DeFunc event to listeners and cleans up members.
bool implIsShowing()
Determines whether the BrowseBox control is really showing inside of its parent accessible window.
virtual void SAL_CALL removeAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &rxListener) override
Removes an event listener.
virtual sal_Bool SAL_CALL supportsService(const OUString &rServiceName) override
virtual void SAL_CALL addAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &rxListener) override
Adds a new event listener.
virtual void SAL_CALL focusGained(const css::awt::FocusEvent &e) override
css::uno::Reference< css::accessibility::XAccessible > mxParent
The parent accessible object.
virtual css::lang::Locale SAL_CALL getLocale() override
virtual css::awt::Point SAL_CALL getLocationOnScreen() override
void commitEvent(sal_Int16 nEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue)
Commits an event to all listeners.
tools::Rectangle getBoundingBox()
Locks all mutex's and calculates the bounding box relative to the parent window.
virtual void SAL_CALL focusLost(const css::awt::FocusEvent &e) override
BrowseBoxAccessibleElement(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, ::vcl::IAccessibleTableProvider &rBrowseBox, const css::uno::Reference< css::awt::XWindow > &_xFocusWindow, AccessibleBrowseBoxObjType eObjType)
Constructor sets specified name and description.
static sal_Int32 addEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
static void addEvent(const TClientId _nClient, const css::accessibility::AccessibleEventObject &_rEvent)
static sal_Int32 removeEventListener(const TClientId _nClient, const css::uno::Reference< css::accessibility::XAccessibleEventListener > &_rxListener)
static void revokeClient(const TClientId _nClient)
static void revokeClientNotifyDisposing(const TClientId _nClient, const css::uno::Reference< css::uno::XInterface > &_rxEventSource)
bool Contains(const Point &rPOINT) const
bool Overlaps(const tools::Rectangle &rRect) const
constexpr tools::Long Top() const
constexpr tools::Long Right() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
const Color & GetColor() const
virtual vcl::Window * GetWindowInstance()=0
virtual void FillAccessibleStateSet(sal_Int64 &_rStateSet, AccessibleBrowseBoxObjType _eType) const=0
const Wallpaper & GetBackground() const
bool IsControlFont() const
const Color & GetControlForeground() const
bool IsControlForeground() const
vcl::Font GetControlFont() const
const vcl::Font & GetFont() const
bool IsControlBackground() const
const Color & GetControlBackground() const
css::awt::Size AWTSize(const Size &rVCLSize)
css::awt::Point AWTPoint(const ::Point &rVCLPoint)
css::awt::Rectangle AWTRectangle(const ::tools::Rectangle &rVCLRect)
inline ::tools::Rectangle VCLRectangle(const css::awt::Rectangle &rAWTRect)
inline ::Point VCLPoint(const css::awt::Point &rAWTPoint)
ULONG m_refCount
std::mutex m_aMutex
#define SAL_WARN(area, stream)
::cppu::WeakComponentImplHelper< css::accessibility::XAccessibleContext, css::accessibility::XAccessibleComponent, css::accessibility::XAccessibleEventBroadcaster, css::awt::XFocusListener, css::lang::XServiceInfo > AccessibleBrowseBoxImplHelper
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
::osl::Mutex & getMutex()
IMPLEMENT_FORWARD_XTYPEPROVIDER2(ChildWindowPane, ChildWindowPaneInterfaceBase, Pane)
IMPLEMENT_FORWARD_XINTERFACE2(ChildWindowPane, ChildWindowPaneInterfaceBase, Pane)
void dispose()
ObjectType meObjType
sal_Int16 nId
unsigned char sal_Bool