Line data Source code
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 <sal/config.h>
21 :
22 : #include <boost/noncopyable.hpp>
23 :
24 : #include <toolkit/helper/accessibilityclient.hxx>
25 : #include <toolkit/helper/accessiblefactory.hxx>
26 : #include <osl/module.h>
27 : #include <osl/diagnose.h>
28 : #include <tools/solar.h>
29 :
30 : // #define UNLOAD_ON_LAST_CLIENT_DYING
31 : // this is not recommended currently. If enabled, the implementation will log
32 : // the number of active clients, and unload the acc library when the last client
33 : // goes away.
34 : // Sounds like a good idea, unfortunately, there's no guarantee that all objects
35 : // implemented in this library are already dead.
36 : // Iow, just because an object implementing an XAccessible (implemented in this lib
37 : // here) died, it's not said that everybody released all references to the
38 : // XAccessibleContext used by this component, and implemented in the acc lib.
39 : // So we cannot really unload the lib.
40 :
41 : // Alternatively, if the lib would us own "usage counting", i.e. every component
42 : // implemented therein would affect a static ref count, the acc lib could care
43 : // for unloading itself.
44 :
45 :
46 : namespace toolkit
47 : {
48 :
49 :
50 : using namespace ::com::sun::star::uno;
51 : using namespace ::com::sun::star::accessibility;
52 :
53 : namespace
54 : {
55 : #ifdef UNLOAD_ON_LAST_CLIENT_DYING
56 : static oslInterlockedCount s_nAccessibilityClients = 0;
57 : #endif // UNLOAD_ON_LAST_CLIENT_DYING
58 : #ifndef DISABLE_DYNLOADING
59 : static oslModule s_hAccessibleImplementationModule = NULL;
60 : #endif
61 : static GetStandardAccComponentFactory s_pAccessibleFactoryFunc = NULL;
62 1 : static ::rtl::Reference< IAccessibleFactory > s_pFactory;
63 : }
64 :
65 :
66 : //= AccessibleDummyFactory
67 :
68 : class AccessibleDummyFactory:
69 : public IAccessibleFactory, private boost::noncopyable
70 : {
71 : public:
72 : AccessibleDummyFactory();
73 :
74 : protected:
75 : virtual ~AccessibleDummyFactory();
76 :
77 : private:
78 : oslInterlockedCount m_refCount;
79 :
80 : public:
81 : // IReference
82 : virtual oslInterlockedCount SAL_CALL acquire() SAL_OVERRIDE;
83 : virtual oslInterlockedCount SAL_CALL release() SAL_OVERRIDE;
84 :
85 : // IAccessibleFactory
86 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
87 0 : createAccessibleContext( VCLXButton* /*_pXWindow*/ ) SAL_OVERRIDE
88 : {
89 0 : return NULL;
90 : }
91 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
92 0 : createAccessibleContext( VCLXCheckBox* /*_pXWindow*/ ) SAL_OVERRIDE
93 : {
94 0 : return NULL;
95 : }
96 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
97 0 : createAccessibleContext( VCLXRadioButton* /*_pXWindow*/ ) SAL_OVERRIDE
98 : {
99 0 : return NULL;
100 : }
101 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
102 0 : createAccessibleContext( VCLXListBox* /*_pXWindow*/ ) SAL_OVERRIDE
103 : {
104 0 : return NULL;
105 : }
106 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
107 0 : createAccessibleContext( VCLXFixedHyperlink* /*_pXWindow*/ ) SAL_OVERRIDE
108 : {
109 0 : return NULL;
110 : }
111 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
112 0 : createAccessibleContext( VCLXFixedText* /*_pXWindow*/ ) SAL_OVERRIDE
113 : {
114 0 : return NULL;
115 : }
116 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
117 0 : createAccessibleContext( VCLXScrollBar* /*_pXWindow*/ ) SAL_OVERRIDE
118 : {
119 0 : return NULL;
120 : }
121 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
122 0 : createAccessibleContext( VCLXEdit* /*_pXWindow*/ ) SAL_OVERRIDE
123 : {
124 0 : return NULL;
125 : }
126 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
127 0 : createAccessibleContext( VCLXComboBox* /*_pXWindow*/ ) SAL_OVERRIDE
128 : {
129 0 : return NULL;
130 : }
131 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
132 0 : createAccessibleContext( VCLXToolBox* /*_pXWindow*/ ) SAL_OVERRIDE
133 : {
134 0 : return NULL;
135 : }
136 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >
137 0 : createAccessibleContext( VCLXWindow* /*_pXWindow*/ ) SAL_OVERRIDE
138 : {
139 0 : return NULL;
140 : }
141 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
142 0 : createAccessible( Menu* /*_pMenu*/, sal_Bool /*_bIsMenuBar*/ ) SAL_OVERRIDE
143 : {
144 0 : return NULL;
145 : }
146 : };
147 :
148 :
149 0 : AccessibleDummyFactory::AccessibleDummyFactory()
150 0 : : m_refCount(0)
151 : {
152 0 : }
153 :
154 :
155 0 : AccessibleDummyFactory::~AccessibleDummyFactory()
156 : {
157 0 : }
158 :
159 :
160 0 : oslInterlockedCount SAL_CALL AccessibleDummyFactory::acquire()
161 : {
162 0 : return osl_atomic_increment( &m_refCount );
163 : }
164 :
165 :
166 0 : oslInterlockedCount SAL_CALL AccessibleDummyFactory::release()
167 : {
168 0 : if ( 0 == osl_atomic_decrement( &m_refCount ) )
169 : {
170 0 : delete this;
171 0 : return 0;
172 : }
173 0 : return m_refCount;
174 : }
175 :
176 :
177 : //= AccessibilityClient
178 :
179 :
180 0 : AccessibilityClient::AccessibilityClient()
181 0 : :m_bInitialized( false )
182 : {
183 0 : }
184 :
185 :
186 : #ifndef DISABLE_DYNLOADING
187 0 : extern "C" { static void SAL_CALL thisModule() {} }
188 : #else
189 : extern "C" void *getStandardAccessibleFactory();
190 : #endif
191 :
192 0 : void AccessibilityClient::ensureInitialized()
193 : {
194 0 : if ( m_bInitialized )
195 0 : return;
196 :
197 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
198 :
199 : #ifdef UNLOAD_ON_LAST_CLIENT_DYING
200 : if ( 1 == osl_atomic_increment( &s_nAccessibilityClients ) )
201 : { // the first client
202 : #endif // UNLOAD_ON_LAST_CLIENT_DYING
203 : // load the library implementing the factory
204 0 : if ( !s_pFactory.get() )
205 : {
206 : #ifndef DISABLE_DYNLOADING
207 0 : const OUString sModuleName( SVLIBRARY( "acc" ) );
208 0 : s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, sModuleName.pData, 0 );
209 0 : if ( s_hAccessibleImplementationModule != NULL )
210 : {
211 : const OUString sFactoryCreationFunc =
212 0 : OUString("getStandardAccessibleFactory");
213 : s_pAccessibleFactoryFunc = (GetStandardAccComponentFactory)
214 0 : osl_getFunctionSymbol( s_hAccessibleImplementationModule, sFactoryCreationFunc.pData );
215 :
216 : }
217 : OSL_ENSURE( s_pAccessibleFactoryFunc, "AccessibilityClient::ensureInitialized: could not load the library, or not retrieve the needed symbol!" );
218 : #else
219 : s_pAccessibleFactoryFunc = getStandardAccessibleFactory;
220 : #endif
221 :
222 : // get a factory instance
223 0 : if ( s_pAccessibleFactoryFunc )
224 : {
225 0 : IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() );
226 : OSL_ENSURE( pFactory, "AccessibilityClient::ensureInitialized: no factory provided by the A11Y lib!" );
227 0 : if ( pFactory )
228 : {
229 0 : s_pFactory = pFactory;
230 0 : pFactory->release();
231 : }
232 0 : }
233 : }
234 :
235 0 : if ( !s_pFactory.get() )
236 : // the attempt to load the lib, or to create the factory, failed
237 : // -> fall back to a dummy factory
238 0 : s_pFactory = new AccessibleDummyFactory;
239 : #ifdef UNLOAD_ON_LAST_CLIENT_DYING
240 : }
241 : #endif
242 :
243 0 : m_bInitialized = true;
244 : }
245 :
246 :
247 0 : AccessibilityClient::~AccessibilityClient()
248 : {
249 0 : if ( m_bInitialized )
250 : {
251 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
252 :
253 : #ifdef UNLOAD_ON_LAST_CLIENT_DYING
254 : if( 0 == osl_atomic_decrement( &s_nAccessibilityClients ) )
255 : {
256 : s_pFactory = NULL;
257 : s_pAccessibleFactoryFunc = NULL;
258 : if ( s_hAccessibleImplementationModule )
259 : {
260 : osl_unloadModule( s_hAccessibleImplementationModule );
261 : s_hAccessibleImplementationModule = NULL;
262 : }
263 : }
264 : #endif // UNLOAD_ON_LAST_CLIENT_DYING
265 : }
266 0 : }
267 :
268 :
269 0 : IAccessibleFactory& AccessibilityClient::getFactory()
270 : {
271 0 : ensureInitialized();
272 : OSL_ENSURE( s_pFactory.is(), "AccessibilityClient::getFactory: at least a dummy factory should have been created!" );
273 0 : return *s_pFactory;
274 : }
275 :
276 :
277 3 : } // namespace toolkit
278 :
279 :
280 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|